most of the spell macros require a Roll20 Pro membership, and the installation of the ChatSetAttr, TokenMod, MagicMaster and RoundMaster API Scripts, to allow parameter passing between macros, update of character sheet variables, and marking spell effects on tokens. If you do not have this level of subscription, I highly recommend you get it as a DM, as you get lots of other goodies as well. If you want to know how to load the API Scripts to your game, the RoLL20 API help here gives guidance, or Richard can help you.
Instructions
In order to understand the format of spell macros in this database and how to change or add to them, please refer to the MagicMaster API documentation.',
+ gmnotes:'Change Log:v6.02 16/10/2022 Updated Spiritual Hammer to use weaponised spell functions
v6.01 25/09/2022 Moved to RPGM Library and updated templates
v5.91 14/07/2022 Removed hard-coded whisper commands on database entries as now directed to correct player(s) programmatically
v5.9 06/04/2022 Adapted to use --display-ability command for chaining abilities
v5.8 18/03/2022 Corrected sphere for Locate-Animals-or-Plants
v5.7 23/02/2022 Corrected error in Create Food & Water spell
v5.6 01/01/2022 Added all remaining Priest spells from the PHB
v5.2 - 5.5 Skipped to even up version numbers
v5.11 13/12/2021 Hid non-castable versions of spells
v5.0 31/10/2021 Encoded using machine readable data to support API databases
v4.3.1 01/06/2021 Removed ammo reset calls from long rest macros, as this is now handled by the MagicMaster API long rest function
v4.3 25/02/2021 Eliminated ability macros that are no longer needed for spell use, replaced by MagicMaster API script
v4.2.1 21/02/2021 fixed initial wave of bugs in MagicMaster, and added short & long rest functions.
v4.2 18/02/2021 Integrated with the new MagicMaster API for casting, memorising and viewing spells.
v4.1.2 21/01/2021 Added tip text to numbers of spells at each level explaining the maths
v4.1 15/11/2020 Split macro library workings from spells database, and also added in sheet-flags attribute which, if 1, uses value of sheet-pr-spells-type to determine the size of the spellbook
v4.0 29/10/2020 v4 has the cost of spells turned on, as introduced in v3.4. (v3 macros have them turned off)
v3.5.3 29/10/2020 Fixed bug with initialising sheet variables
v3.5.2 20/10/2020 Added a 1st level spell for Regenerate, which is actually a power that can me regained with a Short Rest.
v3.5.1 12/10/2020 Updated Long Rests to set ammo maximums to ammo remaining, to reflect that any not recovered when you rest are lost
v3.5 06/10/2020 Linked Long Rests with the Campaign Calendar, and prevented Long Rests until the DM does the "End of Day" procedure to charge daily costs.
v3.4.1 29/09/2020 Bug fix to allow older character sheets to use Short & Long Rests without errors.
v3.4 24/09/2020 Added costs of materials as \'max\' value of CT- spell entries, then deduct from gold when cast.
v3.3 18/09/2020 Changed to normally cast at spell-casters level, and allow separate change to level if needed. Constructed so casting level and caster\'s name can be set separately
3.2.1 16/09/2020 Tweaked for Lost & Found campaign
v3.2 05/09/2020 Updated all the marker effect names to cater for the new Effect functionality, and allow multiple overlapping spell effects to work properly
v3.1 01/09/2020 Added the ability to [Review] spells from spells known/granted to the character before Memorising them.
v3.0 25/08/2020 Vetted & updated ready for Roger\'s campaign. Also changed all calls to !tj to take \'--\' as the command introducer and allow multiple commands in one call and forcing execution in order, so as to overcome asynchronous processing issues.
v2.8 23/08/2020 Added all 1st & 2nd level Priest Spells, and ensured all othre spells were internally consistent.
v2.7 17/8/2020 Saving throw buttons were missing their \'!\', and so did not even appear! Fixed
v2.6 8/8/2020 Changed whispers /w using Token_name to instead use Character_name, as if they were different, errors occurred.
v2.5 6/8/2020 Coordinated and updated all effect markers across all MIs and Spell libraries.
v2.4 3/8/2020 Added the PR-Spells-menu macro to provide a succinct menu to access PR-Spell functions.
v2.3 31/7/2020 Added the ability for spells to mark tokens with markers to indicate spell effects and durations
v2.2 16/7/2020 Added multiple spell use macros to cater for current spell knowledge in SB\'s Desecrated Temple party
v2.1 12/7/2020 Updated and corrected bugs in the Cast-spell, Memorise-Ln-spells, Reset-spells and Blank-Spellbook macros
v2.0 10/7/2020 Conversion of all spells to use default Roll Templates, with API Buttons for relevant dice rolls. Addition of the Spellbook macro, and the capability to have a list of known spells from which spells for the day can be memorised.
v1.0 Initial release',
+ controlledby:'all',
+ root:'PR-Spells-DB',
+ api:'magic',
+ type:'spells',
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/163483347/1CLiNzi4jlxXK1-lVr7MTQ/max.png?1599726214',
+ version:6.02,
+ db:[{name:'-',type:'',ct:'0',charge:'uncharged',cost:'0',body:'@{selected|token_name} thinks there are more spells he can learn...'},
+ {name:'Abjure',type:'PRspellL4',ct:'10',charge:'uncharged',cost:'100',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAbjure\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration}}{{sphere=Summoning}}Specs=[Abjure,PRspellL4,1H,Abjuration]{{components=V,S,M}}{{time=[[10]]}}{{range=[10 yds](!rounds --aoe @{selected|token_id}|circle|yards|0|20||lightning|true)}}{{duration=Special}}{{aoe=1 creature}}{{save=[Special](!\\amp#13;\\amp#47;r 1d20 see Abjuration spell specs)}}{{reference=PHB p215}}SpellData=[w:Abjure,lv:4,sp:10,gp:100,cs:VSM,sph:Summoning]{{effects=Send an extraplanar creature back to its own plane of existence.}}{{materials=The priest\'s holy symbol, holy water, and some material inimical to the creature, worth at least 100gp.}}'},
+ {name:'Aerial-Servant',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAerial Servant\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning}}{{sphere=Summoning}}Specs=[Aerial Servant,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[9]]}}{{range=[[[10]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||magic|true)}}{{duration=[[@{selected|casting-level}]] days}}{{aoe=Special}}{{save=None}}{{reference=PHB p226}}SpellData=[w:Aerial Servant,lv:6,sp:9,gp:0,cs:VS,sph:Summoning]{{effects=Summons an invisible aerial servant to find and bring back an object or creature described to it by the priest.}}'},
+ {name:'Aid',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0.02',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAid\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Necromancy,Conjuration}}{{sphere=Necromantic}}Specs=[Aid,PRspellL2,1H,Necromancy|Conjuration]{{components=V,S,M}}{{time=[[5]]}}{{range=Touch}}{{duration=[[1+@{selected|Casting-Level}]] rounds}}{{aoe= Creature touched}}{{save=None}}{{healing=[Give Aid](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first to aid|token_id}|Aid|[[1+@{selected|Casting-Level}]]|-1|Received Aid, +1 on attk, +saves vs fear, +extra HP|angel-outfit)}}{{reference=PHB p202}}SpellData=[w:Aid,lv:2,sp:5,gp:0.02,cs:VSM,sph:Necromantic]{{effects=Recipient gains +[[1]] to THAC0 and saves vs Fear. Also adds [1d8](!\\amp#13;\\amp#47;r 1d8) hit points for duration of spell. Damage comes first off the extra Hit Points. These points cannot be regained via cures.\nUsing the *Give Aid* button will automatically adjust Thac0 \\amp HP for the correct duration}}{{materials=A tiny strip of white cloth (worth 2cp) with a sticky substance (such as tree sap) on the ends, plus the priest\'s holy symbol.}}'},
+ {name:'Air-Breathing',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAir Breathing\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Air)}}Specs=[Air-Breathing,PRspellL3,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=Touch}}{{duration=[[?{How many air breathers?|1}]] creatures for [[floor(@{selected|casting-level}/?{How many air breathers?|1})]]hours [[floor((60*@{selected|casting-level}/?{How many air breathers?|1})%60)]] minutes}}{{aoe=Special}}{{save=None}}{{healing=[Grant lungs](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Give aqualung to who?|token_id}|Air-Breathing|[[60*@{selected|casting-level}/([[?{How many air breathers?|1}]])]]|-1|Breath air like a person|ninja-mask)}}{{reference=PHB p215}}SpellData=[w:Air-Breathing,lv:3,sp:6,gp:0,cs:VS,sph:Elemental-Air]{{effects=Enables water-breathing creatures to survive comfortably in the atmosphere for the duration of the spell--i.e., one hour for each experience level of the caster.}}'},
+ {name:'Air-Walk',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAir Walk\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration}}{{sphere=Elemental (Air)}}Specs=[Air Walk,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch}}{{duration=[[6+@{selected|Casting-Level}]] turns}}{{aoe=[[1]] creature}}{{save=None}}{{healing=[Step lightly on air](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who wants to be walking in the air?|token_id}|Air-Walk|[[60+(10*@{selected|casting-level})]]|-1|You\'re walking through the air!|fluffy-wing)}}{{reference=PHB p221}}SpellData=[w:Air Walk,lv:5,sp:8,gp:0.01,cs:VSM,sph:Elemental-Air]{{effects=Enables a creature, which can be as big as the largest giant, to tread upon air as if it were walking on solid ground.}}{{materials=The priest\'s holy symbol and a bit of thistledown at a cost of 1cp}}'},
+ {name:'Animal-Friendship',type:'PRspellL1',ct:'600',charge:'uncharged',cost:'0.05',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimal Friendship\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Animal-Friendship,PRspellL1,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[1]] hour}}{{range=[10 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||magic|true)}}{{duration=Permanent}}{{aoe=[[1]] animal per spell casting}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p198}}SpellData=[w:Animal-Friendship,lv:1,sp:600,gp:0.05,cs:VSM,sph:Animal]{{effects=Attracts up to [[2*@{selected|Casting-Level}]] HD animals. Max number of HD of animals as friends at any time is 2x caster\'s level at that time.}}{{materials=Caster\'s holy symbol and food that the animal likes worth 5cp.}}'},
+ {name:'Animal-Growth',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimal Growth\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest (Reversable)}}{{school=Alteration}}{{sphere=Animal}}Specs=[Animal Growth,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=[[80]] yards}}{{duration=[[2*@{selected|Casting-Level}]] rounds}}{{aoe=Up to [[8]] creatures in a [20ft. square](!rounds --aoe @{selected|token_id}|square|feet|240|20||magic)}}{{save=None}}{{reference=PHB p221}}{{healing=[Grow](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which animals to grow?|token_id}|Animal-Growth|[[2*@{selected|casting-level}]]|-1|Wow! So big - HDx2, HPx2, dmg x 2|strong)}}SpellData=[w:Animal Growth,lv:5,sp:8,gp:0.01,cs:VSM,sph:Animal]{{effects=Causes up to eight animals within a 20-foot square area to grow to twice their normal size, doubling Hit Dice (with resultant improvement in attack potential), hit points (except hit points added to Hit Dice), and damage in combat.}}{{materials=The priest\'s holy symbol and a scrap of food, cost 1cp}}'},
+ {name:'Animal-Summoning-1',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimal Summoning 1\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Conjuration,Summoning}}{{sphere=Animal,Summoning}}Specs=[Animal-Summoning-1,PRspellL4,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[7]]}}{{range=[[1]]mile radius}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p216}}SpellData=[w:Animal-Summoning-1,lv:4,sp:7,gp:0,cs:VS,sph:Animal|Summoning]{{effects=Calls up to eight animals that have 4 Hit Dice or less, of whatever sort the caster names when the summoning is made.}}'},
+ {name:'Animal-Summoning-II',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimal Summoning II\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Conjuration,Summoning}}{{sphere=Animal,Summoning}}Specs=[Animal-Summoning-II,PRspellL5,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[8]]}}{{range=[[[60*@{selected|casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[120*@{selected|casting-level}]]||magic|true)}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p221}}SpellData=[w:Animal-Summoning-II,lv:5,sp:8,gp:0,cs:VS,sph:Animal|Summoning]{{effects=Calls up to six animals of 8 Hit Dice or less, or 12 animals of 4 Hit Dice or less--of whatever sort the caster names.}}'},
+ {name:'Animal-Summoning-III',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimal Summoning III\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration,Summoning}}{{sphere=Animal,Summoning}}Specs=[Animal-Summoning-III,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[[100*@{selected|casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[200*@{selected|casting-level}]]||magic|true)}}{{time=[[9]]}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p226}}SpellData=[w:Animal-Summoning-III,lv:6,sp:9,gp:0,cs:VS,sph:Animal|Summoning]{{effects=Calls up to four animals of [[16]] Hit Dice or less, or eight of no more than [[8]] Hit Dice, or 16 animals of [[4]] Hit Dice or less--of whatever sort the caster names that are in range.}}'},
+ {name:'Animate-Object',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimate Object\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Creation, Summoning}}Specs=[Animate Object,PRspellL6,1H,Alteration]{{components=V,S}}{{range=[[30]] yards}}{{time=[[9]]}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Animate-Object|@{selected|casting-level}|-1|Animating an object|spanner)}}{{aoe=[@{selected|casting-level} cu.ft.](!rounds --aoe @{selected|token_id}|rectangle|feet|90|||magic)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Animate Object spell)}}{{reference=PHB p226}}SpellData=[w:Animate Object,lv:6,sp:9,gp:0,cs:VS,sph:Creation|Summoning]{{effects=Imbue inanimate objects with mobility and a semblance of life.}}'},
+ {name:'Animate-Rock',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimate Rock\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Elemental (Earth)}}Specs=[Animate Rock,PRspellL7,1H,Alteration]{{components=V,S,M}}{{range=[[40]] yards}}{{time=[[1]] round}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Animate-Rock|@{selected|casting-level}|-1|Animated a rock which will obay simple commands|edge-crack)}}{{aoe=[[[2*@{selected|casting-level}]] cu.ft.](!rounds --movable-aoe @{selected|token_id}|rectangle|feet|120|||magic)}}{{save=None}}{{reference=PHB p230}}SpellData=[w:Animate Rock,lv:7,sp:10,gp:0,cs:VSM,sph:Elemental-Earth]{{effects=Causes a separated stone object of up to the indicated size to move (see the 6th-level *animate object* spell.), following the desire of the caster--attacking, breaking objects, blocking--while the magic lasts.}}{{materials=A stone and drop of the caster\'s blood, costing nothing}}'},
+ {name:'Animate-dead',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnimate Dead\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Necromancy}}{{sphere=Necromantic}}Specs=[Animate-Dead,PRspellL3,1H,Necromancy]{{components=V,S,M}}{{time=[[10]]}}{{range=[10 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||magic|true)}}{{duration=Permanent}}{{aoe=Special}}{{save=None}}{{reference=PHB p208}}SpellData=[w:Animate-Dead,lv:3,sp:10,gp:10,cs:VSM,sph:Necromantic]{{effects=Creates the lowest of the undead monsters, skeletons or zombies, usually from the bones or bodies of dead humans, demihumans, or humanoids.}}{{materials=A drop of blood, a piece of flesh of the type of creature being animated, and a pinch of bone powder or a bone shard - 10gp as some types of flesh are hard to retrieve}}'},
+ {name:'Anti-Animal-Shell',type:'PRspellL6',ct:'10',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnti-Animal Shell\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Abjuration}}{{sphere=Animal, Protection}}Specs=[Anti-Animal Shell,PRspellL6,1H,Abjuration]{{components=V,S,M}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Anti-Animal-Shell|[[10*@{selected|casting-level}]]|-1|Protected by the Anti-Animal shell|white-tower)}}{{range=[[0]]}}{{time=[[1]] round}}{{aoe=[[10]] ft. radius (moves with caster)}}{{save=None}}{{reference=PHB p226}}SpellData=[w:Anti-Animal Shell,lv:6,sp:10,gp:0.01,cs:VSM,sph:Animal|Protection]{{effects=Brings into being a hemispherical force field that prevents the entrance of any sort of living creature that is wholly or partially animal (not magical or extraplanar).}}{{materials=The caster\'s holy symbol and a handful of pepper, costing 1cp}}'},
+ {name:'Anti-Plant-Shell',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAnti-Plant Shell\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Abjuration}}{{sphere=Plant, Protection}}Specs=[Anti-Plant Shell,PRspellL5,1H,Abjuration]{{components=V,S}}{{time=[[8]]}}{{range=[[0]]}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Anti-plant-shell|[[10*@{selected|casting-level}]]|-1|Protected from plant attack|white-tower)}}{{aoe=15ft Diameter}}{{save=None}}{{reference=PHB p221}}SpellData=[w:Anti-Plant Shell,lv:5,sp:8,gp:0,cs:VS,sph:Plant|Protection]{{effects=Creates an invisible, mobile barrier that keeps all creatures within the shell protected from attacking plants or vegetable creatures such as shambling mounds or treants.}}'},
+ {name:'Astral-Spell',type:'PRspellL7',ct:'300',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAstral Spell\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Astral}}Specs=[Astral Spell,PRspellL7,1H,Alteration]{{components=V,S}}{{range=Touch}}{{time=[[3]] turns}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p231}}SpellData=[w:Astral Spell,lv:7,sp:300,gp:0,cs:VS,sph:Astral]{{effects=A priest is able to project his astral body into the Astral plane, leaving his physical body and material possessions behind on the Prime Material plane.}}'},
+ {name:'Atonement',type:'PRspellL5',ct:'100',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAtonement\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Abjuration}}{{sphere=All}}Specs=[Atonement,PRspellL5,1H,Abjuration]{{components=V,S,M}}{{time=[[1]] turn}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 person}}{{save=None}}{{reference=PHB p221}}SpellData=[w:Atonement,lv:5,sp:100,gp:1000,cs:VSM,sph:All]{{effects=Remove the burden of unwilling or unknown deeds from the person who is the subject of the atonement. The spell removes the effects of magical alignment changes as well.}}{{materials=The priest\'s religious symbol, prayer beads or wheel or book, and burning incense, and a donation of 1,000gp to the temple}}'},
+ {name:'Attack-target',type:'',ct:'0',charge:'uncharged',cost:'0',body:'**@{selected|token_name} hits AC [[( ([[@{selected|thac0}]]) - ([[@{selected|strengthhit}]]) - [[1d20]] )]] with his spell.**\n/w "@{selected|character_name}" If hit, [Cast on them](!magic --target single|@{selected|token_id}|@{target|Who are you Attacking?|token_id}|@{selected|Spell-cast}|@{selected|Spell-duration}|@{selected|Spell-direction}|@{selected|Spell-msg}|@{selected|Spell-marker})'},
+ {name:'Augury',type:'PRspellL2',ct:'2',charge:'uncharged',cost:'50',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nAugury\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Augury,PRspellL2,1H,Divination]{{components=V,S,M}}{{time=[[2]] rounds}}{{range=[[0]]}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p203}}SpellData=[w:Augury,lv:2,sp:2,gp:50,cs:VSM,sph:Divination]{{effects=Asks divine guidance on whether action in next [[3]] turns will be for the benefit of or harmful to the party. If successful DM will reveal "weal" or "Woe" or perhaps some cryptic clue. Chance of success is [[70+@{selected|Casting-Level}]]% adjusted by DM for circumstances.}}{{materials=A set of gem-inlaid sticks, dragon bones, or similar tokens of at least 1,000gp value (which are ***not*** expended in casting and can be used up to 20 times)}} '},
+ {name:'Badberry',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nBadberry\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration,Evocation (reversable)}}{{sphere=Plant}}Specs=[Badberry,PRspellL2,1H,Alteration|Evocation]{{components=V,S,M}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[1+@{selected|Casting-Level}]] days}}{{aoe=[2d4](!\\amp#13;\\amp#47;r 2d4) rotten berries}}{{save=None}}{{damage=[[1]]HP per berry}}{{reference=PHB p205}}SpellData=[w:Badberry,lv:2,sp:10,gp:0,cs:VSM,sph:Plant]{{effects=Causes 2d4 rotten berries to appear wholesome, but each actually delivers 1 point of poison damage (no saving throw) if ingested}}{{materials=The caster\'s holy symbol passed over the freshly picked, edible berries to be enspelled (blueberries, blackberries, raspberries, currants, gooseberries, etc.). No cost}}'},
+ {name:'Barkskin',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nBarkskin\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Protection,Plant}}Specs=[Barkskin,PRspellL2,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=Touch}}{{duration=[[4+@{selected|Casting-Level}]] rounds}}{{aoe=Creature touched}}{{save=None}}{{healing=[Wear Barkskin](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who makes like a tree?|token_id}|Barkskin|[[4+@{selected|Casting-Level}]]|-1|Skin like bark, AC improved, +1 save except spell|bolt-shield)}}{{reference=PHB p203}}SpellData=[w:Barkskin,lv:2,sp:5,gp:0.01,cs:VSM,sph:Protection|Plant]{{effects=A selected creature\'s skin becomes as tough as bark, increasing its base Armor Class to AC 6, plus 1 AC for every four levels of the priest.\nSelecting the *Wear Barkskin* button and then selecting the target creature will automatically apply the correct AC for the correct duration.}}{{materials=The priest\'s holy symbol and a handful of bark from an oak, costing 1cp}}'},
+ {name:'Bestow-Curse',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nBestow Curse\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Bestow-Curse,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[6]]}}{{range=Touch}}{{duration=[[@{selected|casting-level}]]turns}}{{aoe=Special}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{damage=[Bestow curse](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who do you curse?|token_id}|Cursed|[[10*@{selected|casting-level}]]|-1|Curse bestowed - determined by DM \\amp/or caster|radioactive)}}{{reference=PHB p213 (reverse *Remove Curse*)}}SpellData=[w:Bestow-Curse,lv:3,sp:6,gp:1,cs:VS,sph:Protection]{{effects=Causes one of the following effects (roll percentile dice):\n[Roll percentile dice](!\\amp#13;\\amp#47;r 1d100)\n1-50 Lowers one ability of the subject to 3 (the DM determines which by random selection)\n51-75 Worsens the subject\'s attack rolls and saving throws by -4\n76-00 Makes the subject 50% likely per turn to drop whatever it is holding (or simply do nothing, in the case of creatures not using tools)}}'},
+ {name:'Blade-Barrier',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nBlade Barrier\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Evocation}}{{sphere=Guardian, Creation}}Specs=[Blade Barrier,PRspellL6,1H,Evocation]{{components=V,S}}{{duration=[[[3*@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Blade-Barrier|[[3*@{selected|casting-level}]]|-1|The blade barrier continues|all-for-one)}}{{range=[[30]] yards}}{{time=[[9]]}}{{aoe=[5 to 60 ft. sq.](!rounds --aoe @{selected|token_id}|square|feet|90|||lightning)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Blade Barrier spell)}}{{reference=PHB p227}}{{damage=[8d8](!\\amp#13;\\amp#47;r 8d8 damage from passing through Blade Barrier)HP}}SpellData=[w:Blade Barrier,lv:6,sp:9,gp:0,cs:VS,sph:Guardian|Creation]{{effects=Set up a wall of circling, razor-sharp blades which whirl and flash around a central point, creating an immobile barrier.}}'},
+ {name:'Bless',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nBless\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Conjuration/Summoning}}{{sphere=All}}Specs=[Bless,PRspellL1,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[60]] yards}}{{duration=[[6]] rounds}}{{aoe=[50ft cube](!range --aoe @{selected|token_id}|square|feet|180|50||light)}}{{save=None}}{{reference=PHB p198}}{{healing=[Bless them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first supplicant|token_id}|Bless|6|-1|Blessed, attk+1, save vs fear+1|angel-outfit)}}SpellData=[w:Bless,lv:1,sp:10,gp:1,cs:VSM,sph:All]{{effects=Raises morale of friendly creatures *not yet in melee combat* adding +[[1]] to saves vs. fear effects and raises attack rolls by +[[1]]. Or can cast on a single object weighing no more than [[@{selected|Casting-Level}]] pounds and the plus lasts until the item is used or the duration ends}}{{marterials=Holy Water}}'},
+ {name:'CLW',type:'PRspellL1',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Light Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[CLW,PRspellL1,1H,Necromancy]{{components=V,S}}{{time=[[5]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p199}}{{healing=[1d8](!\\amp#13;\\amp#47;r 1d8) HP,\nor [1d8+3](!\\amp#13;\\amp#47;r 1d8+3) for a Priest of Life}}SpellData=[w:CLW,lv:1,sp:5,gp:0,cs:VS,sph:Healing]{{effects=Cannot cure non-corporeal or nonliving or extra-planar creatures.}}'},
+ {name:'Call-Lightning',type:'PRspellL3',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCall Lightning\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Call-Lightning,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=[[@{selected|Casting-Level}]] turns}}{{aoe= [360ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|720||lightning)}}{{save=[To Half](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209}}{{damage= [(level+2)d8](!\\amp#13;\\amp#47;r [[2+@{selected|Casting-Level}]]d8)}}SpellData=[w:Call-Lightning,lv:3,sp:100,gp:0,cs:VSM,sph:Weather]{{effects=Call down bolts on lightning, one bolt per turn (for [[1]] turn/level). When cast there must be a storm of some sort in the area such as a rain shower, clouds and wind, or even a tornado (including a whirlwind created by a djinn or air elemental).}}{{materials=A storm overhead}}'},
+ {name:'Call-Woodland-Beings',type:'PRspellL4',ct:'200',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCall Woodland Beings\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Conjuration,Summoning}}{{sphere=Summoning}}Specs=[Call-Woodland-Beings,PRspellL4,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=Special}}{{range=[[100*@{selected|Casting-level}]]yds}}{{duration=Special}}{{aoe=Special}}{{save=[Negates](!\\amp#13;\\amp#47;r 1d20 Save vs Call Woodland Beings spell)}}{{reference=PHB p216}}SpellData=[w:Call-Woodland-Beings,lv:4,sp:200,gp:0.01,cs:VSM,sph:Summoning]{{effects=Summon certain woodland creatures to the caster\'s location.}}{{materials=A pine cone and eight holly berries, costing 1cp to preserve.}}'},
+ {name:'Cause-Blindness-not-deafness',type:'PRspellL0',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Blindness or Deafness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cause-Blindness-or-Deafness,PRspellL0,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209 (reverse Cure Blindness or Deafness)}}{{damage=Select type below then [Touch](~Selected|To-Hit-Spell)}}SpellData=[w:Cause-Blindness-or-Deafness,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Requires a successful touch (successful attack roll) on the victim, and a failed save vs. spell to cause a non-damaging magical blindness. Alternatively the victim can be [deafened](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cause-Deafness-not-Blindness). A ***blinded*** creature suffers a -4 penalty to its attack rolls, a +4 penalty to its Armor Class, and a +2 penalty to its initiative rolls.}}\n!magic --touch @{selected|token_id}|Blindness|99|0|Blinded, Penalty of 4 to attk,AC|bleeding-eye'},
+ {name:'Cause-Critical-Wounds',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Critical Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Healing}}Specs=[Cause-Critical-Wounds,PRspellL5,1H,Necromancy]{{components=V,S}}{{time=[[8]]}}{{range=Touch Attack}}{{duration=Permanent}}{{aoe=Creature Touched}}{{save=None}}{{reference=PHB p222}}{{damage=[3d8+3](!\\amp#13;\\amp#47;r 3d8+3) HP,\nor [3d8+10](!\\amp#13;\\amp#47;r 3d8+10) for a Priest of Death}}SpellData=[w:Cause-Critical-Wounds,lv:5,sp:8,gp:0,cs:VS,sph:Healing]{{effects=Cannot damage non-corporeal or nonliving or extraplanar creatures}}'},
+ {name:'Cause-Deafness-not-Blindness',type:'PRspellL0',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Blindness or Deafness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cause-Blindness-or-Deafness,PRspellL0,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209 (reverse Cure Blindness or Deafness)}}{{damage=Select type below then [Touch](~Selected|To-Hit-Spell)}}SpellData=[w:Cause-Blindness-or-Deafness,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Requires a successful touch (successful attack roll) on the victim, and a failed save vs. spell to cause a non-damaging magical deafness.\nA ***deafened*** creature can react only to what it can see or feel, and suffers a -1 penalty to surprise rolls, a +1 penalty to its initiative rolls, and a 20% chance of spell failure for spells with verbal components.\nAlternatively, a victim can be [blinded](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cause-Blindness-not-Deafness)}}\n!magic --touch @{selected|token_id}|Deafness|99|0|Deafened, 1 penalty on surprise + initiative, 20% spell fail|bleeding-eye'},
+ {name:'Cause-Fear',type:'PRspellL1',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Fear\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Abjuration}}{{sphere=Charm}}Specs=[Cause-Fear,PRspellL1,1H,Abjuration]{{components=V,S}}{{time=[[1]]}}{{range=[10 yds](!rounds --aoe @{selected|token_id}|circle|yards|0|20||dark|true)}}{{duration=1d4 rounds}}{{aoe=[[1]] creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p202 (reverse Remove Fear)}}{{damage=[Scare Them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a victim|token_id}|Cause-Fear|\\amp#91;[1d4]\\amp#93;|-1|Frightened, flee at maximum rate|screaming)}}SpellData=[w:Cause-Fear,lv:1,sp:1,gp:0,cs:VS,sph:Charm]{{effects=Cause fear causes one creature to flee in panic at maximum movement speed away from the caster for 1d4 rounds.}}'},
+ {name:'Cause-Light-Wounds',type:'PRspellL1',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Light Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cause-Light-Wounds,PRspellL1,1H,Necromancy]{{components=V,S}}{{time=[[5]]}}{{range=[Touch](!attk --attk-hit @{selected|token_id})}}{{duration=Permanent}}{{aoe=Creature touched}}{{save=None}}{{healing=[1d8](!\\amp#13;\\amp#47;r 1d8) HP,\nor [1d8+3](!\\amp#13;\\amp#47;r 1d8+3) for a Priest of Life}}{{reference=PHB p199 (reverse Cure Light Wounds)}}SpellData=[w:Cause-Light-Wounds,lv:1,sp:5,gp:0,cs:VS,sph:Healing]{{effects=Operates in the same manner as Cure Light Wounds, but inflicting 1d8 points of damage instead of curing. If a creature is avoiding this touch, a Touch attack is required to inflict the damage. Cannot damage non-corporeal or nonliving or extra-planar creatures.}}'},
+ {name:'Cause-Serious-Wounds',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Serious Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cause-Serious-Wounds,PRspellL4,1H,Necromancy]{{components=V,S}}{{time=[[7]]}}{{range=Touch attack}}{{duration=Permanent}}{{aoe=Creature Touched}}{{save=None}}{{reference=PHB p217}}{{damage=[2d8+1](!\\amp#13;\\amp#47;r 2d8+1) HP}}SpellData=[w:Cause-Serious-Wounds,lv:4,sp:7,gp:0,cs:VS,sph:Healing]{{effects=The victim has to be touched first - use a Touch weapon attack. If the touch is successful, 2d8+1 points of damage are inflicted}}'},
+ {name:'Cause-blindness-or-deafness',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Blindness or Deafness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cause-Blindness-or-Deafness,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209 (reverse Cure Blindness or Deafness)}}{{damage=Select type below then [Touch]}}SpellData=[w:Cause-Blindness-or-Deafness,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Requires a successful touch (successful attack roll) on the victim. If the victim rolls a successful saving throw, the effect is negated. If the saving throw is failed, a non-damaging magical blindness or deafness results.\nA [deafened](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cause-Deafness-not-Blindness) creature can react only to what it can see or feel, and suffers a -1 penalty to surprise rolls, a +1 penalty to its initiative rolls, and a 20% chance of spell failure for spells with verbal components. A [blinded](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cause-Blindness-not-Deafness) creature suffers a -4 penalty to its attack rolls, a +4 penalty to its Armor Class, and a +2 penalty to its initiative rolls.}}\n!magic --touch @{selected|token_id}|Deafness|99|0|Deafened, 1 penalty on surprise + initiative, 20% spell fail|bleeding-eye'},
+ {name:'Cause-disease',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCause Disease\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cause-Disease,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209 (reverse Cure Disease)}}{{damage=Select type below then [Touch](~Selected|To-Hit-Spell)}}SpellData=[w:Cause-Disease,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Touch the intended victim to cause a disease (debilitating or fatal) unless save vs. spell. The exact details of the disease are decided by the DM., but the following are typical:\n[*Debilitating:*](!magic --touch @{selected|token_id}|Debilitating-disease|[[10*1d6]]|-1|Infected with debilitating disease which has yet to take effect|rolling-bomb) or [*Fatal:*](!magic --touch @{selected|token_id}|Fatal-disease|99|0|Fatal disease infection, cure wounds spells don\'t work, heal at 10% of normal|skull)}}\n!magic --touch @{selected|token_id}|Debilitating-disease|[[10*1d6]]|-1|Infected with debilitating disease which has yet to take effect|rolling-bomb'},
+ {name:'Changestaff',type:'PRspellL7',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nChangestaff\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation, Enchantment}}{{sphere=Plant, Creation}}Specs=[Changestaff,PRspellL7,1H,Evocation|Enchantment]{{components=V,S,M}}{{range=Touch}}{{time=[[4]]}}{{duration=[@{selected|casting-level} turns](!rounds --target caster|@{selected|token_id}|Changestaff|[[10*@{selected|casting-level}]]|-1|Your staff is acting as a treant, 12HD, 40HP, AC0|three-leaves)}}{{aoe=The caster\'s staff}}{{save=None}}{{reference=PHB p231}}SpellData=[w:Changestaff,lv:7,sp:4,gp:0,cs:VSM,sph:Plant|Creation]{{effects=Change a specially prepared staff into a treantlike creature of the largest size, about 24 feet tall.}}{{materials=Either his holy symbol or leaves (ash, oak, or yew) of the same sort as the staff (no cost)}}'},
+ {name:'Chant',type:'PRspellL2',ct:'20',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nChant\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Conjuration/Summoning}}{{sphere=Combat}}Specs=[Chant,PRspellL2,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[2]] rounds}}{{range=[[0]] yards}}{{duration=Time of chanting}}{{aoe=[30ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||magic|true)}}{{save=None}}{{reference=PHB p209}}{{healing=Select [friend](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first friend|token_id}|Chant-ally|99|0|Chanting, 1 bonus on attk,dmg,saves|angel-outfit) or [foe](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first foe|token_id}|Chant-foe|99|0|Chanting, 1 penalty on attk,dmg,saves|radioactive) 1-by-1 then do the other type}}SpellData=[w:Chant,lv:2,sp:20,gp:0,cs:VS,sph:Combat]{{effects=Brings special favour upon the caster and their party, and causes harm to his enemies.}}{{materials=Holy Water (no cost).}}'},
+ {name:'Chariot-of-Sustarre',type:'PRspellL7',ct:'100',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nChariot of Sustarre\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation}}{{sphere=Elemental (Fire), Creation}}Specs=[Chariot of Sustarre,PRspellL7,1H,Evocation]{{components=V,S,M}}{{range=[[10]] yards}}{{time=[[1]] turn}}{{duration=[12 hours](!rounds --target caster|@{selected|token_id}|Chariot of Sustarre|720|-1|You have a flaming flying chariot, move 24, FL 48|overdrive)}}{{aoe=Special}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs petrification)}}{{reference=PHB p231}}SpellData=[w:Chariot of Sustarre,lv:7,sp:100,gp:0.01,cs:VSM,sph:Elemental-Fire|Creation]{{effects=Brings forth a large, flaming chariot pulled by two fiery horses from the elemental plane of Fire in a clap of thunder amid a cloud of smoke.}}{{materials=A small piece of wood, two holly berries, and a fire source at least equal to a torch. Total cost 1cp}}'},
+ {name:'Charm-Person-or-Mammal',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCharm Person or Mammal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Charm-Person-or-Mammal,PRspellL2,1H,Enchantment-Charm]{{components=V,S}}{{time=[[5]]}}{{range=[80 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|160||magic)}}{{duration=Special - at least 1 day}}{{aoe=[[1]] person or mammal}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{damage=[Charm them!](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select new friend|token_id}|Charm-P-or-M|99|0|Charmed|chained-heart)}}{{reference=PHB p203}}SpellData=[w:Charm-Person-or-Mammal,lv:2,sp:5,gp:0,cs:VS,sph:Animal]{{effects=Charm one person, humanoid man size or smaller, or mammal. Save vs. spell or believes caster is trusted friend and ally to be protected.}}'},
+ {name:'Chill-Metal',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nChill Metal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Elemental(Fire)}}Specs=[Chill-Metal,PRspellL2,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=[40 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|80||cold|true)}}{{duration=[[7]] rounds}}{{aoe= [[floor(@{selected|Casting-Level}/2)]] man-sized equivalent area of metal}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p205}}{{damage=[Hey... Chill!](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select what to chill|token_id}|Chill-Metal|7|-1|Chilling metal, increasing dmg|frozen-orb)}}SpellData=[w:Chill-Metal,lv:2,sp:5,gp:0,cs:VSM,sph:Elemental-Fire]{{effects=Makes ferrous metal very cold but not Elven chain. Magical armour saves vs. magical cold (DMG p38) for no effect.\nRound 1 and 7 uncomfortable.\nRound 2 and 6 [1d2](!\\amp#13;\\amp#47;r 1d2) damage.\nRound 3 / 4 / 5 does [1d4](!\\amp#13;\\amp#47;r 1d4) damage.\n\nIn round 5 must save vs. spell or suffer numbing effects of cold. Causes loss of feeling in a hand (or hands, if DM rules save failed badly) for 1d4 days. Character\'s grip extremely week \\amp cannot use for fighting or any activity requiring firm grip.}}{{materials=The metal to be chilled}}'},
+ {name:'Cloak-of-Bravery',type:'PRspellL4',ct:'6',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCloak of Bravery\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Conjuration,Summoning}}{{sphere=Summoning}}Specs=[Cloak-of-Bravery,PRspellL4,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[6]]}}{{range=Touch}}{{duration=Special}}{{aoe=1 to 4 creatures}}{{save=None}}{{reference=PHB p216}}{{healing=[Become a Hero](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Cloak which heroes?|token_id}|Bravery|99|0|Wearing Cloak of Bravery so save +4 / 3 / 2 / 1 vs Fear|Strong)}}SpellData=[w:Cloak-of-Bravery,lv:4,sp:6,gp:1,cs:VSM,sph:Summoning]{{effects=The protected individual(s) gain a bonus to their saving throw against any form of fear encountered (but not awe--an ability of some lesser and greater powers).}}{{materials=the feather of an eagle or hawk, often costing 1gp in the market}}'},
+ {name:'Cloak-of-Fear',type:'PRspellL4',ct:'6',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCloak of Fear\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Conjuration,Summoning}}{{sphere=Summoning}}Specs=[Cloak-of-Fear,PRspellL4,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[6]]}}{{range=Touch}}{{duration=Special}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;r 1d20 save vs Cloak of Fear spell)}}{{reference=PHB p216 (reverse Cloak of Bravery)}}{{healing=[Wrap in Fear](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s Scary?|token_id}|Cloak_of_Fear|99|0|Scary person - save or run for 2d8)}}SpellData=[w:Cloak-of-Fear,lv:4,sp:6,gp:0.01,cs:VSM,sph:Summoning]{{effects=Empowers a single creature touched to radiate a personal aura of fear, at will, out to a 3-foot radius.}}{{materials=The tail feathers of a vulture or chicken (1cp).}}'},
+ {name:'Combine',type:'PRspellL1',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCombine\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Evocation}}{{sphere=All}}Specs=[Combine,PRspellL1,1H,Evocation]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Special}}{{aoe=Circle of Priests}}{{save=None}}{{reference=PHB p198}}SpellData=[w:Combine,lv:1,sp:7,gp:0,cs:VS,sph:All]{{effects=Three to five priests combine their abilities so that one of them casts spells and turns undead at an enhanced level.}}'},
+ {name:'Command',type:'PRspellL1',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCommand\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Enchantment/Charm}}{{sphere=Charm}}Specs=[Command,PRspellL1,0H,Enchantment-Charm]{{components=V}}{{time=[[1]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[[1]] round}}{{aoe=[[1]] creature}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p199}}SpellData=[w:,lv:1,sp:1,gp:0,cs:V,sph:Charm]{{effects=Command another creature with a single word, such as *back / halt / flee / run / stop / fall / go / leave / surrender / sleep / rest* etc.}}'},
+ {name:'Commune',type:'PRspellL5',ct:'100',charge:'uncharged',cost:'0.07',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCommune\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Commune,PRspellL5,1H,Divination]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]] questions}}{{aoe=Special}}{{save=None}}{{reference=PHB p222}}SpellData=[w:Commune,lv:5,sp:100,gp:0.07,cs:VSM,sph:Divination]{{effects=The priest is able to contact his deity--or agents thereof--and request information in the form of questions that can be answered by a simple "yes" or "no."}}{{materials=The priest\'s religious symbol, holy (unholy) water, and incense worth 7cp}}'},
+ {name:'Commune-With-Nature',type:'PRspellL5',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCommune With Nature\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Divination}}{{sphere=Divination, Elemental}}Specs=[Commune With Nature,PRspellL5,1H,Divination]{{components=V,S}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]] facts become known}}{{aoe=Special}}{{save=None}}{{reference=PHB p222}}SpellData=[w:Commune With Nature,lv:5,sp:100,gp:0,cs:VS,sph:Divination|Elemental]{{effects=Become one with nature, thus being empowered with knowledge of the surrounding territory.}}'},
+ {name:'Confusion',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nConfusion\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Enchantment-Charm}}{{sphere=Charm}}Specs=[Confusion,PRspellL7,1H,Enchantment-Charm]{{components=V,S,M}}{{range=[[80]] yards}}{{time=[[1]] round}}{{duration=[[@{selected|casting-level}]] rounds}}{{aoe=[[[1d4+floor(@{selected|casting-level}/2)]] creatures](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who\'s confused?|token_id}|Confusion|@{selected|casting-level}|-1|This is so confusing! This round roll is 1d10|broken-skull) in [40ft.sq.](!rounds --aoe @{selected|token_id}|square|feet|240|40||magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs Confusion spell)}}{{reference=PHB p231}}SpellData=[w:Confusion,lv:7,sp:10,gp:0.01,cs:VSM,sph:Charm]{{effects=Causes confusion in one or more creatures within the area, creating indecision and the inability to take effective action.}}{{materials=A set of three nut shells, costing 1cp to source}}'},
+ {name:'Conjure-Animals',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nConjure Animals\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning}}{{sphere=Summoning}}Specs=[Conjure-Animals,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{duration=[[[2*@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Conjure Animals|[[2*@{selected|casting-level}]]|-1|The conjured animal continues to do your bidding|half-heart)}}{{range=[[[30]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{time=[[9]]}}{{aoe=Special}}{{save=None}}{{reference=PHB p227}}SpellData=[w:Conjure Animals,lv:6,sp:9,gp:0,cs:VS,sph:Summoning]{{effects=Magically create one or more mammals to attack his opponents.}}'},
+ {name:'Conjure-Earth-Elemental',type:'PRspellL7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nConjure Earth Elemental\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Elemental (Earth), Summoning}}Specs=[Conjure Earth Elemental,PRspellL7,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[[40]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|80||magic|true)}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Conjure-Earth-Elemental|[[10*@{selected|casting-level}]]|-1|The Earth Elemental continues to do your bidding... for now|fist)}}{{time=[[1]] turn}}{{aoe=Special}}{{save=None}}{{reference=PHB p232}}SpellData=[w:Conjure Earth Elemental,lv:7,sp:100,gp:0,cs:VS,sph:Elemental-Earth|Summoning]{{effects=An Earth Elemental is summoned. [[60]]% likely (01-60) to have 12 Hit Dice, [[35]]% likely (61-95) to have 16 Hit Dice, and [[5]]% likely (96-00) have [21 to 24](!\\amp#13;\\amp#47;r 20+1d4) Hit Dice. Roll [Percentile dice](!\\amp#13;\\amp#47;r 1d100).}}'},
+ {name:'Conjure-Fire-Elemental',type:'PRspellL6',ct:'60',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nConjure Fire Elemental\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Elemental (Fire)}}Specs=[Conjure Fire Elemental,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[[80]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|160||magic|true)}}{{time=[[6]] rounds}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Conjure-Fire-Elemental|[[10*@{selected|casting-level}]]|-1|The conjured elemental continues to do your bidding|half-heart)}}{{aoe=Special}}{{save=None}}{{reference=PHB p227}}SpellData=[w:Conjure Fire Elemental,lv:6,sp:60,gp:0,cs:VS,sph:Elemental-Fire]{{effects=A fire elemental is summoned [[65]]% (1-65) likely that a 12 Hit Dice elemental appears, [[20]]% (66-85) likely that a 16 Hit Dice elemental appears,[[9]]% (86-94) likely that [two to four](!\\amp#13;\\amp#47;r 1d3+1) salamanders appear, [[4]]% (95-98) likely that an efreeti appears, and [[2]]% (99-00) likely that a huge fire elemental of [21 to 24](!\\amp#13;\\amp#47;r 1d4+20) Hit Dice appears.\nRoll [Percentile dice](!\\amp#13;\\amp#47;r 1d100).}}'},
+ {name:'Continual-Darkness',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nContinual Darkness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Sun}}Specs=[Continual-Darkness,PRspellL3,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=[[120]] yards}}{{duration=Permanent}}{{aoe=[60ft radius sphere](!rounds --aoe @{selected|token_id}|circle|yards|120|40||black)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209 (reverse Continual Light)}}SpellData=[w:Continual-Darkness,lv:3,sp:6,gp:0,cs:VS,sph:Sun]{{effects=This spell is similar to a *darkness* spell, except that it is as dark as a cave with no light source and lasts until negated by magical light or by a dispel magic spell.}}'},
+ {name:'Continual-Light',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nContinual Light\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Sun}}Specs=[Continual-Light,PRspellL3,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=[[120]] yards}}{{duration=Permanent}}{{aoe=[60ft radius sphere](!rounds --aoe @{selected|token_id}|circle|yards|120|40||light)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209}}SpellData=[w:Continual-Light,lv:3,sp:6,gp:0,cs:VS,sph:Sun]{{effects=This spell is similar to a light spell, except that it is as bright as full daylight and lasts until negated by magical darkness or by a dispel magic spell.}}'},
+ {name:'Control-Temperature-10ft-Radius',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.02',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nControl-Temperature-10ft-Radius\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Control-Temperature-10ft-radius,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=0}}{{duration=[[4+@{selected|casting-level}]]turns}}{{aoe=[10ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|20||magic)}}{{save=None)}}{{reference=PHB p216}}SpellData=[w:Control-Temperature-10ft-radius,lv:4,sp:7,gp:0.02,cs:VSM,sph:Weather]{{effects=The temperature surrounding the caster can be altered by 10 F., either upward or downward, per level of experience of the spellcaster (a total of [[10*@{selected|casting-level}]] F).\nThe spell also provides protection from intense normal and magical thermal attacks.}}{{materials=A strip of willow bark (to lower temperatures) or raspberry leaves (to raise temperatures, 1cp each)}}'},
+ {name:'Control-Weather',type:'PRspellL7',ct:'100',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nControl Weather\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Control Weather,PRspellL7,1H,Alteration]{{components=V,S,M}}{{range=[[0]]}}{{time=[[1]] turn}}{{duration=[[4d12]] hours}}{{aoe=[[4d4]] sq. miles}}{{save=None}}{{reference=PHB p232}}SpellData=[w:Control Weather,lv:7,sp:100,gp:0.5,cs:VSM,sph:Weather]{{effects=Change the weather in the local area. It requires an additional [1d4](!\\amp#13;\\amp#47;r 1d4) turns for the effects of the spell to be felt.}}{{materials=The priest\'s religious symbol, incense, and prayer beads or similar prayer object, total cost 5sp per casting}}'},
+ {name:'Control-Winds',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nControl Winds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Control Winds,PRspellL5,1H,Alteration]{{components=V,S}}{{time=[[8]]}}{{range=[[0]]}}{{duration=[@{selected|casting-level} turns](!rounds --target caster|@{selected|token_id}|Control-Winds|[[10*@{selected|casting-level}]]|-1|Able to control winds|lightning-helix)}}{{aoe=[[[40*@{selected|casting-level}]]ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|[[80*@{selected|casting-level}]]||lightning|true)}}{{save=None}}{{reference=PHB p222}}SpellData=[w:Control Winds,lv:5,sp:8,gp:0,cs:VS,sph:Weather]{{effects=Alter wind force in the area of effect. The caster can increase or decrease wind force by [[floor(@{selected|casting-level}/3)]] levels of strength. Wind strengths are as follows:\n\nWind Force ...... Miles Per Hour\nLight Breeze ........... 2-7\nModerate Breeze ..... 8-18\nStrong Breeze ........ 19-31\nGale ..................... 32-54\nStorm ................... 55-72\nHurricane .............. 73-176}}'},
+ {name:'Create-Food-and-Water',type:'PRspellL3',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCreate Food and Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Creation}}Specs=[Create-Food-and-Water,PRspellL3,1H,Alteration]{{components=V,S}}{{time=[[1]]turn}}{{range=[[10]] yards}}{{duration=Special}}{{aoe=[[@{selected|casting-level}]]cu.ft.}}{{save=None}}{{reference=PHB p209}}SpellData=[w:Create-Food-and-Water,lv:3,sp:100,gp:0,cs:VS,sph:Creation]{{effects=Causes food and water to appear.}}'},
+ {name:'Create-Water',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCreate-Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Create-Water,PRspellL1,1H,Alteration]{{components=V,S,M}}{{time=[[1]]round}}{{range=[30 yds](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=Permanent}}{{aoe=Up to [[27]]cu.ft}}{{save=None}}{{reference=PHB p199}}SpellData=[w:,lv:1,sp:10,gp:0,cs:VSM,sph:Elemental-Water]{{effects=Up to four gallons of water are generated for every experience level of the caster}}{{materials=The create water spell requires at least a drop of water.}}'},
+ {name:'Creeping-Doom',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCreeping Doom\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning}}{{sphere=Animal, Summoning}}Specs=[Creeping Doom,PRspellL7,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[0]]}}{{time=[[1]] round}}{{duration=[[4*@{selected|casting-level}]] rounds}}{{aoe=[20ft. sq. movable](!rounds --movable-aoe @{selected|token_id}|bolt|feet|0|20|20|acid)}}{{save=None}}{{reference=PHB p232}}SpellData=[w:Creeping Doom,lv:7,sp:10,gp:0,cs:VS,sph:Animal|Summoning]{{effects=Calls forth a mass of from 500 to 1,000 [(1d6 + 4) x 100](!\\amp#13;\\amp#47;r 100*(4+1d6\\amp#41;) venomous, biting and stinging arachnids, insects, and myriapods.}}'},
+ {name:'Cure-Better',type:'PRspellL2',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Better\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Healing,Necromantic}}{{sphere=Healing}}Specs=[Cure-Better,PRspellL2,1H,Necromantic]{{components=V,S}}{{time=[[6]]}}{{range=touch}}{{duration=Permanent}}{{aoe=[[1]] creature}}{{save=None}}{{healing=[1d8+1](!\\amp#13;\\amp#47;r 1d8+1),\nor [1d8+5](!\\amp#13;\\amp#47;r 1d8+5) for a Priest of Life}}SpellData=[w:Cure-Better,lv:2,sp:6,gp:0,cs:VS,sph:Healing]{{effects=The God of Healing created this new spell to help his clerics, but knowledge is creeping out into the wider community. \nIt is fundamentally the same as a “Cure Light Wounds Spell” except it cures [1d8+1](!\\amp#13;\\amp#47;r 1d8+1) points of damage in the hands of a generalist cleric, or one not of the Healing pantheon. (And takes slightly longer to cast)\nIn the hands of a priest of Life however, due to the bonuses they get, it cures [1d8+5](!\\amp#13;\\amp#47;r 1d8+5) points of damage.}}'},
+ {name:'Cure-Critical-Wounds',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Critical Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Healing}}Specs=[Cure-Critical-Wounds,PRspellL5,1H,Necromancy]{{components=V,S}}{{time=[[8]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature Touched}}{{save=None}}{{healing=[3d8+3](!\\amp#13;\\amp#47;r 3d8+3) HP,\nor [3d8+10](!\\amp#13;\\amp#47;r 3d8+10) for a Priest of Life}}{{reference=PHB p222}}SpellData=[w:Cure-Critical-Wounds,lv:5,sp:8,gp:0,cs:VS,sph:Healing]{{effects=Cannot cure non-corporeal or nonliving or extraplanar creatures. Can restore someone between [[0-1]] and [[0-10]] to [[0]]HP.}}'},
+ {name:'Cure-Further',type:'PRspellL2',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Further\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Healing,Necromantic}}{{sphere=Healing}}Specs=[Cure-Further,PRspellL2,1H,Necromantic]{{components=V,S}}{{time=[[6]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=Permanent}}{{aoe=[[1]] creature}}{{save=None}}{{healing=[1d8](!\\amp#13;\\amp#47;r 1d8),\nor [1d8+4](!\\amp#13;\\amp#47;r 1d8+4) for a Priest of Life}}SpellData=[w:Cure-Further,lv:2,sp:6,gp:0,cs:VS,sph:Healing]{{effects=The God of Healing created this new spell to help his clerics, but knowledge is creeping out into the wider community. \nIt is fundamentally the same as a Cure Light Wounds Spell except it can be cast on someone 30 yards away. in the hands of a generalist cleric, or one not of the Healing pantheon it cures [1d8](!\\amp#13;\\amp#47;r 1d8) points of damage. \nIn the hands of a priest of Life however, due to the bonuses they get, it cures [1d8+4](!\\amp#13;\\amp#47;r 1d8+4) points of damage.}}'},
+ {name:'Cure-Light-Wounds',type:'PRspellL1',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Light Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[CLW,PRspellL1,1H,Necromancy]{{components=V,S}}{{time=[[5]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p199}}{{healing=[1d8](!\\amp#13;\\amp#47;r 1d8) HP,\nor [1d8+3](!\\amp#13;\\amp#47;r 1d8+3) for a Priest of Life}}SpellData=[w:Cure-Light-Wounds,lv:1,sp:5,gp:0,cs:VS,sph:Healing]{{effects=Cannot cure non-corporeal or nonliving or extra-planar creatures.}}'},
+ {name:'Cure-Serious-Wounds',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Serious Wounds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cure-Serious-Wounds,PRspellL4,1H,Necromancy]{{components=V,S}}{{time=[[7]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature Touched}}{{save=None}}{{reference=PHB p217}}{{healing=[2d8+1](!\\amp#13;\\amp#47;r 2d8+1) HP,\nor [2d8+7](!\\amp#13;\\amp#47;r 2d8+7) for a Priest of Life}}SpellData=[w:Cure-Serious-Wounds,lv:4,sp:7,gp:0,cs:VS,sph:Healing]{{effects=Cannot cure non-corporeal or nonliving or extraplanar creatures. Can restore someone between [[0-1]] and [[0-10]] to [[0]]HP.}}'},
+ {name:'Cure-blindness-or-deafness',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Blindness or Deafness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cure-Blindness-or-Deafness,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p209}}SpellData=[w:Cure-Blindness-or-Deafness,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=By touching the creature afflicted, the priest employing the spell can permanently cure some forms of blindness or deafness. This spell does not restore or repair visual or auditory organs damaged by injury or disease.\nIts reverse, cause blindness or deafness, is a different spell macro}}'},
+ {name:'Cure-disease',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCure Disease\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cure-Disease,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p209}}SpellData=[w:Cure-Disease,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Cure most diseases by placing his hand upon the diseased creature. The affliction rapidly disappears thereafter, making the cured creature whole and well in from one turn to 10 days, depending on the type of disease and the state of its advancement when the cure took place (the DM must adjudicate these conditions).}}'},
+ {name:'Curse',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nCurse (Reverse Bless)\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Conjuration/Summoning}}{{sphere=All}}Specs=[Curse,PRspellL1,1H,Conjuration]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[60]] yards}}{{duration=[[6]] rounds}}{{aoe=[50ft cube](!rounds --aoe @{selected|token_id}|square|feet|60|50||dark)}}{{save=None}}{{reference=PHB p198 (reverse Bless)}}{{damage=[Curse them!](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first cursed one|token_id}|Curse|6|-1|Cursed, 1 penalty on morale \\amp attk|radioactive)}}SpellData=[w:,lv:1,sp:10,gp:0,cs:VSM,sph:All]{{effects=Only effects enemies not already in combat lowering their morale and attack roles by [[0-1]]. Selecting the *Curse them* button automatically changes their Thac0 for the correct duration}}{{materials=A sprinkling of Unholy Water (no cost).}}'},
+ {name:'Darkness',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDarkness\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Alteration}}{{sphere=Sun}}Specs=[Darkness,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[4]]}}{{range=[[120]] yards}}{{duration=1 hour + [[@{selected|Casting-Level}]] turns}}{{aoe=[20ft radius globe](!rounds --aoe @{selected|token_id}|circle|feet|360|40||black)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p201 (reverse Light)}}{{damage=[Blind them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to brighten|token_id}|Light|[[60+(10*@{selected|Casting-Level})]]|-1|Blinded by the Darkness in eyes, 4 penalty on attk+AC|bleeding-eye)}}SpellData=[w:Darkness,lv:1,sp:4,gp:0,cs:VS,sph:Sun]{{effects=Equal to the darkest night. Immobile unless cast on a movable object or creature. If on a creature, magic resistance and save vs. spell applies.}}'},
+ {name:'Destroy-Water',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDestroy Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Destroy-Water,PRspellL1,1H,Alteration]{{components=V,S,M}}{{time=[[1]]round}}{{range=[30 yds](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=Permanent}}{{aoe=Up to [[27]]cu.ft}}{{save=None}}{{reference=PHB p199}}SpellData=[w:Destroy Water,lv:1,sp:10,gp:0,cs:VSM,sph:Elemental-Water]{{effects=Obliterates without trace (no vapor, mist, fog, or steam) up to [[4*@{selected|casting-level}]] gallons of water.}}{{materials=At least a pinch of dust (no cost).}}'},
+ {name:'Detect-Charm',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect Charm\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Detect-Charm,PRspellL2,1H,Divination]{{components=V,S}}{{time=[[1]] round}}{{range=[30 yds](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[[1]] turn}}{{aoe=[[@{selected|Casting-Level}]] creatures}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p204}}SpellData=[w:Detect-Charm,lv:2,sp:10,gp:0,cs:VS,sph:Divination]{{effects=Detect if a person or monster is under the influence of a charm spell, or similar control such as hypnosis, suggestion, beguiling, possession, etc.}}'},
+ {name:'Detect-Evil',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect-Evil\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Divination}}{{sphere=All}}Specs=[Detect-Evil,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[1]]round}}{{range=[[0]]}}{{duration=[[10+(5*@{selected|Casting-Level})]] rounds}}{{aoe=[10ft x 120yds path](!rounds --aoe @{selected|token_id}|bolt|feet|0|360|10|magic)}}{{save=None}}{{reference=PHB p199}}{{healing=[Evil radar on](!rounds --target caster|@{selected|token_id}|Detect-Evil|[[10+(5*@{selected|Casting-Level})]]|-1|Detecting Evil|aura)}}SpellData=[w:Detect-Evil,lv:1,sp:10,gp:0,cs:VS,sph:Divination]{{effects=This spell discovers emanations of evil from any creature, object, or area. Character alignment, however, is revealed only under unusual circumstances: characters who are strongly aligned, who do not stray from their faith, and who are of at least 9th level might radiate evil *if intent upon appropriate actions.*}}{{materials=The priest\'s holy symbol, with the priest holding it before him.}}'},
+ {name:'Detect-Good',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect Good\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Divination}}{{sphere=All}}Specs=[Detect-Good,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[1]]round}}{{range=[[0]]}}{{duration=[[10+(5*@{selected|Casting-Level})]] rounds}}{{aoe=[10ft x 120yds path](!rounds --aoe @{selected|token_id}|bolt|feet|0|360|10|magic)}}{{save=None}}{{reference=PHB p199 (reverse Detect Evil)}}{{healing=[Good radar on](!rounds --target caster|@{selected|token_id}|Detect-Good|[[10+(5*@{selected|Casting-Level})]]|-1|Detecting Good|aura)}}SpellData=[w:Detect-Good,lv:1,sp:10,gp:0,cs:VS,sph:Divination]{{effects=Discovers emanations of good from any creature, object, or area. Character alignment, however, is revealed only under unusual circumstances: characters who are strongly aligned, who do not stray from their faith, and who are of at least 9th level might radiate good *if intent upon appropriate actions.*}}{{materials=The priest\'s un-holy symbol, with the priest holding it before him.}}'},
+ {name:'Detect-Lie',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect Lie\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest (reversable)}}{{school=Divination}}{{sphere=Divination}}Specs=[Detect-Lie,PRspellL4,1H,Divination]{{components=V,S,M}}{{time=[[7]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=[[1]] creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs spell for detect lie)}}{{reference=PHB p217}}{{healing=[Attach Polygraph](!rounds --target caster|@{selected|token_id}|Detect-Lie|[[@{selected|Casting-Level}]]|-1|Detecting Lies|aura)}}SpellData=[w:,lv:4,sp:7,gp:1,cs:VSM,sph:Divination]{{effects=Immediately able to determine if the subject creature deliberately and knowingly speaks a lie.}}{{materials=one gp worth of gold dust}}'},
+ {name:'Detect-Magic',type:'PRspellL1',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect-Magic\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Detect-Magic,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[30]] yds}}{{duration=[[1]] Turn}}{{aoe=[10ft path](!rounds --aoe @{selected|token_id}|rectangle|feet|0|90|10|magic)}}{{save=None}}{{reference=PHB p199}}SpellData=[w:Detect-Magic,lv:1,sp:100,gp:0,cs:VSM,sph:Divination]{{effects=Detects magical radiations in a path [[10]] feet wide and up to 30 yards long, in the direction the caster is facing.}}{{materials=Use of the priest\'s holy symbol}}'},
+ {name:'Detect-Poison',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect Poison\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Detect-Poison,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[1]] Turn + [[@{selected|Casting-Level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p199}}SpellData=[w:Detect-Poison,lv:1,sp:4,gp:10,cs:VSM,sph:Divination]{{effects=This spell enables the priest to determine if an object has been poisoned or is poisonous. One object, or one [[5]] foot cubic mass, can be checked per round. The priest has a [[5*@{selected|Casting-Level}]]% chance of determining the exact type of poison}}{{materials=A strip of specially blessed vellum, costing a 10gp donation to the temple, which turns black if poison is present}}'},
+ {name:'Detect-Snares-and-Pits',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDetect Snares and Pits\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Detect-Snares-and-Pits,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[4*@{selected|Casting-Level}]] rounds}}{{aoe=[10ft path, 40ft long](!rounds --aoe @{selected|token_id}|rectangle|feet|0|40|10|magic)}}{{save=None}}{{reference=PHB p200}}SpellData=[w:Detect-Snares-and-Pits,lv:1,sp:4,gp:0,cs:VSM,sph:Divination]{{effects=Detect snares, pits, deadfalls and similar hazards along a path 10 feet wide and 40 feet long.}}{{materials=The Priest\'s holy symbol}}'},
+ {name:'Dismiss-Earth-Elemental',type:'PRspellL7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDismiss Earth Elemental\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Elemental (Earth), Summoning}}Specs=[Dismiss Earth Elemental,PRspellL7,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[[40]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|80||magic|true)}}{{time=[[1]] turn}}{{duration=Instantaneous}}{{aoe=Special}}{{save=None}}{{reference=PHB p232}}SpellData=[w:Dismiss Earth Elemental,lv:7,sp:100,gp:0,cs:VS,sph:Elemental-Earth|Summoning]{{effects=Dismisses an earth elemental conjured by a *conjure earth elemental* spell or similar means.}}'},
+ {name:'Dismiss-Fire-Elemental',type:'PRspellL6',ct:'60',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDismiss Fire Elemental\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Elemental (Fire)}}Specs=[Dismiss Fire Elemental,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[[80]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|160||magic|true)}}{{time=[[6]] rounds}}{{duration=Instantaneous}}{{aoe=1 Fire Elemental}}{{save=None}}{{reference=PHB p227}}SpellData=[w:Dismiss Fire Elemental,lv:6,sp:60,gp:0,cs:VS,sph:Elemental-Fire]{{effects=Sends a Fire Elemental back to the plane it came from. Dispels a *Conjure Fire Elemental* spell}}'},
+ {name:'Dispel-Evil',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDispel Evil\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Abjuration (Reversable)}}{{sphere=Protection, Summoning}}Specs=[Dispel Evil,PRspellL5,1H,Abjuration]{{components=V,S,M}}{{time=[[8]]}}{{range=[Touch attack](!attk --attk-hit @{selected|token_id})}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Dispel-Evil|@{selected|casting-level}|-1|Able to Dispel Evil, and evil attks get -7 penalty|white-tower)}}{{aoe=Dispel 1 creature}}{{reference=PHB p222}}{{save=None}}SpellData=[w:Dispel Evil,lv:5,sp:8,gp:0.01,cs:VSM,sph:Protection|Summoning]{{effects=Causes a summoned creature of evil nature, an evil creature from another plane, or a creature summoned by an evil caster, to return to its own plane or place when the caster successfully strikes it in melee combat.}}{{materials=The priest\'s religious object and holy water costing 1cp}}'},
+ {name:'Dispel-Good',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDispel Good\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Abjuration (Reversable)}}{{sphere=Protection, Summoning}}Specs=[Dispel Good,PRspellL5,1H,Abjuration]{{components=V,S,M}}{{time=[[8]]}}{{range=[Touch attack](!attk --attk-hit @{selected|token_id})}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Dispel-Good|@{selected|casting-level}|-1|Able to Dispel Good, and good attks get -7 penalty|white-tower)}}{{aoe=Dispel 1 creature}}{{reference=PHB p222}}{{save=None}}SpellData=[w:Dispel Good,lv:5,sp:8,gp:0.01,cs:VSM,sph:Protection|Summoning]{{effects=Causes a summoned creature of good nature, a good creature from another plane, or a creature summoned by a good caster, to return to its own plane or place when the caster successfully strikes it in melee combat.}}{{materials=The priest\'s religious object and unholy water costing 1cp}}'},
+ {name:'Dispel-Hallucinatory-Forest',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDispel Hallucinatory Forest\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Illusion/Phantasm}}{{sphere=Plant}}Specs=[Dispel-Hallucinatory-Forest,PRspellL4,1H,Illusion-Phantasm]{{components=V,S}}{{time=[[7]]}}{{range=[[80]yds}}{{duration=Permanent}}{{aoe=[[[40*@{selected|casting-level}]]sq.ft.](!rounds --aoe @{selected|token_id}||feet|240|||green)}}{{save=None}}{{reference=PHB p218 (reverse Hallucinatory Forect)}}SpellData=[w:Dispel-Hallucinatory-Forest,lv:4,sp:7,gp:0,cs:VS,sph:Plant]{{effects=This spell does nothing other than dispel a hallucinatory forest created by the spell of the same name.}}'},
+ {name:'Dispel-Magic',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDispel Magic\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Dispel-Magic,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[6]]}}{{range=[[60]] yards}}{{duration=Special}}{{aoe=[30ft cube](!rounds --aoe @{selected|token_id}|square|yards|60|10||magic) or [1 item](!rounds --aoe @{selected|token_id}|circle|yards|0|120||magic)}}{{save=Other creature\'s item [Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Dispel Magic spell)}}{{reference=PHB p210}}SpellData=[w:Dispel-Magic,lv:3,sp:6,gp:0,cs:VS,sph:Protection]{{effects=Grants a chance to neutralize or negate the magic it comes in contact with.}}'},
+ {name:'Divination',type:'PRspellL4',ct:'100',charge:'uncharged',cost:'50',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDispel Magic\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Divination,PRspellL4,1H,Divination]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p217}}SpellData=[w:,lv:4,sp:100,gp:50,cs:VSM,sph:Divination]{{effects=Garner a useful piece of advice concerning a specific goal, event, or activity that will occur within a one-week period. This can be as simple as a short phrase, or it might take the form of a cryptic rhyme or omen. Unlike the augury spell, this gives a specific piece of advice.}}{{materials=a sacrificial offering worth a minimum 50gp, incense, and the holy symbol of the priest. If an unusually important divination is attempted, sacrifice of particularly valuable gems, jewellery, or magical items may be required.}}'},
+ {name:'Dust-Devil',type:'PRspellL2',ct:'20',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDust Devil\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Conjuration/Summoning}}{{sphere=Elemental(Air)}}Specs=[Dust-Devil,PRspellL2,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[2]] rounds}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||lightning|true)}}{{duration=[[2*@{selected|Casting-Level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p204}}SpellData=[w:Dust-Devil,lv:2,sp:20,gp:0,cs:VS,sph:Elemental-Air]{{effects=Conjures a weak air elemental AC[[4]] / [[2]]HD / move [[18]] / [[1]] attack of [1d4](!\\amp#13;\\amp#47;r 1d4) / can be hit by normal weapons. Appears as small whirlwind 1ft dia at base / 5ft tall / 3ft to 4ft across at top. Moves as directed by priest but dissipates if out of range.}}'},
+ {name:'Earthquake',type:'PRspellL7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEarthquake\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Elemental (Earth)}}Specs=[Earthquake,PRspellL7,1H,Alteration]{{components=V,S,M}}{{range=[[120]] yards}}{{time=[[1]] turn}}{{duration=[[1]] round}}{{aoe=[[[5*@{selected|casting-level}]]ft diameter](!rounds --aoe @{selected|token_id}|circle|feet|360|[[5*@{selected|casting-level}]]||lightning)}}{{save=None}}{{reference=PHB p233}}SpellData=[w:Earthquake,lv:7,sp:100,gp:0,cs:VSM,sph:Elemental-Earth]{{effects=A local tremor of fairly high strength rips the ground. The shock is over in one round.}}{{materials=A pinch of dirt, a piece of rock, and a lump of clay (no cost)}}'},
+ {name:'Endure-Cold',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEndure Cold\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Protection}}Specs=[Endure-Cold,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[3*@{selected|Casting-Level}/2]] hours}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p200}}{{healing=[Grant Endurance](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a beneficiary|token_id}|Endure-Cold|99|0|Can endure cold to -34C, absorb 10HP of magic cold|white-tower)}}SpellData=[w:Endure-Cold,lv:1,sp:10,gp:0,cs:VS,sph:Protection]{{effects=Can withstand normal extremes of cold down to [[0-30]]F ([[0-34]]C) and suffers [[1]]HP per hour per degree below this. Magical cold (or heat) will break spell but first [[10]]HP will be absorbed. Ends immediately if either type of Resist spell is cast on recipient}}'},
+ {name:'Endure-Heat',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEndure Heat\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Protection}}Specs=[Endure-Heat,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[3*@{selected|Casting-Level}/2]] hours}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p200}}{{healing=[Grant Endurance](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a beneficiary|token_id}|Endure-Heat|99|0|Can endure heat to 54C, absorb 10HP of magic heat|white-tower)}}SpellData=[w:Endure-Heat,lv:1,sp:10,gp:0,cs:VS,sph:Protection]{{effects=Can withstand normal extremes of heat up to [[130]]F ([[54]]C) and suffers [[1]]HP per hour per degree above this. Magical fire will break spell but first [[10]]HP will be absorbed. Ends immediately if either type of Resist spell is cast on recipient}}'},
+ {name:'Entangle',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEntangle\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Entangle,PRspellL1,1H,Alteration]{{components=V, S, M}}{{time=[[4]]}}{{range=[[80]] yards}}{{duration=[[1]] turn or [[10]] rounds}}{{aoe=[40 foot cube](!rounds --aoe @{selected|token_id}|square|feet|240|40||magic)}}{{save=[Reduced movement](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p200}}{{damage=[Entangle them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first entangled creature|token_id}|Entangle|10|-1|Entangled, immobile|cobweb)}}SpellData=[w:Entangle,lv:1,sp:4,gp:0,cs:VSM,sph:Plant]{{effects=Causes grass, weeds, bushes and even trees to wrap, twist and entwine about creatures in the Area of Effect, which must then Save vs. Spell or be held fast.}}{{materials=The caster\'s holy symbol}}'},
+ {name:'Enthrall',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEnthrall\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Charm}}Specs=[Enthrall,PRspellL2,1H,Enchantment-Charm]{{components=V,S}}{{time=[[1]]round}}{{range=[[0]]}}{{duration=Special}}{{aoe=[90ft radius](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p204}}{{healing=[Enthrall Them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first audience member|token_id}|Enthrall|99|0|Enthralled while caster speaks unless attacked|chained-heart)}}SpellData=[w:Enthrall,lv:2,sp:10,gp:0,cs:VS,sph:Charm]{{effects=Enthrall an audience that can fully understand his language, which must save vs. spell or give the caster their undivided attention, totally ignoring their surroundings.}}'},
+ {name:'Exaction',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nExaction\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation, Alteration}}{{sphere=Charm, Summoning}}Specs=[Exaction,PRspellL7,1H,Evocation|Alteration]{{components=V,S,M}}{{range=[[10]] yards}}{{time=[[1]] round}}{{duration=Special}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p233}}SpellData=[w:Exaction,lv:7,sp:10,gp:1000,cs:VSM,sph:Charm|Summoning]{{effects=Confront some powerful creature from another plane (including devas and other powerful minions, for instance, but not demigods or deities of any sort) and requires of it some duty or quest.}}{{materials=The priest\'s holy symbol, some matter or substance from the plane of the creature from whom an exaction is expected costing 1,000gp to source, and knowledge of the creature\'s nature or actions that is written out on a parchment that is burned to seal the pledge}}'},
+ {name:'Faerie-Fire',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFaerie Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Faerie-Fire,PRspellL1,1H,Alteration]{{components=V,M}}{{time=[[4]]}}{{range=[[80]] yards}}{{duration=[[4*@{selected|Casting-Level}]] rounds}}{{aoe=[[10*@{selected|Casting-Level}]] sq.ft. within [40ft radius](!rounds --aoe @{selected|token_id}|circle|feet|240|80||light)}}{{save=None}}{{reference=PHB p200}}{{damage=Select one of the two buttons below, *darkness* or *twilight*, to target creatures and automatically apply penaties for correct duration}}SpellData=[w:Faerie-Fire,lv:1,sp:4,gp:10,cs:VM,sph:Weather]{{effects=Outline creatures in 40ft radius of each other with a total of [[10*@{selected|pr-Casting-Level}]]sq.ft of faerie fire - the square footage relates to the surface area of the targets. In [darkness](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Faerie-Fire-darkness|[[4*@{selected|Casting-Level}]]|-1|Outlined in bright Faerie Fire, 2 penalty to AC|aura) +[[2]] on attacks against outlined creatures or +[[1]] in [twilight](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Faerie-Fire-twilight|[[4*@{selected|Casting-Level}]]|-1|Outlined in dim Faerie Fire, 1 penalty to AC|aura) or brighter. A [[2]]nd level priest will outline [[2]] human sized creatures.}}{{materials=A small piece of foxfire, costing10gp.}}'},
+ {name:'False-Seeing',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'300',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFalse Seeing\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Divination (Reversable)}}{{sphere=Divination}}Specs=[False Seeing,PRspellL5,1H,Divination]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch}}{{duration=[[@{selected|casting-level}]] rounds}}{{aoe=[1 creature](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who will see falsely?|token_id}|False-Seeing|@{selected|casting-level}|-1|Can you believe your eyes?|bleeding-eye)}}{{save=None}}{{reference=PHB p225}}SpellData=[w:False Seeing,lv:5,sp:8,gp:300,cs:VSM,sph:Divination]{{effects=Causes the person to see things as they are not: rich is poor, rough is smooth, beautiful is ugly. The victim must be fooled, charmed or otherwise persuaded to use the ointment}}{{materials=An ointment for the eyes that is made from oil, poppy dust, and pink orchid essence and costs no less than 300 gp per use \\amp 1d6 months to make}}'},
+ {name:'Feign-Death',type:'PRspellL3',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFeign-Death\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Necromancy}}{{sphere=Necromantic}}Specs=[Feign-Death,PRspellL3,0H,Necromantic]{{components=V}}{{time=[[1]]}}{{range=Touch}}{{duration=[[10+@{selected|Casting-Level}]]rounds}}{{aoe=Person touched}}{{save=None}}{{reference=PHB p210}}{{healing=[Feign Death](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a target|token_id}|Feign-Death|[[10+@{selected|Casting-Level}]]|-1|Catatonic state, can\'t feel or see, 1 / 2 dmg to body|skull)}}SpellData=[w:Feign-Death,lv:3,sp:1,gp:0,cs:V,sph:Necromantic]{{effects=The caster or any other willing person can be put into a cataleptic state that is impossible to distinguish from actual death, in which they can smell, hear, and know what is going on, but no feeling or sight of any sort is possible; thus, any wounding or mistreatment of the body is not felt, no reaction occurs, and damage is only one-half normal.}}'},
+ {name:'Find-Traps',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFind Traps\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Find-Traps,PRspellL2,1H,Divination]{{components=V,S}}{{time=[[5]]}}{{range=[[30]] yards}}{{duration=[[3]] turns}}{{aoe=[10ft path to range](!rounds --aoe @{selected|token_id}|bolt|feet|0|90|10|magic) in direction caster is facing}}{{save=None}}{{reference=PHB p204}}SpellData=[w:Find-Traps,lv:2,sp:5,gp:0,cs:VS,sph:Divination]{{effects=All traps, normal or magical become visible to the caster. Traps meet 3 criteria: can inflict a sudden or unexpected result; spellcaster would view result as undesirable or harmful; and result specifically intended as such by creator.}}'},
+ {name:'Find-the-Path',type:'PRspellL6',ct:'30',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFind the Path\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Divination (Reversable)}}{{sphere=Divination}}Specs=[Find the Path,PRspellL6,1H,Divination]{{components=V,S,M}}{{range=Touch}}{{time=[[3]] rounds}}{{duration=[[@{selected|casting-level}]] turns}}{{aoe=[1 Creature](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Give GPS to whom?|token_id}|Find-the-Path|[[10*@{selected|casting-level}]]|-1|Has a really good sense of direction|flying-flag)}}{{save=None}}{{reference=PHB p227}}SpellData=[w:Find the Path,lv:6,sp:30,gp:0.01,cs:VSM,sph:Divination]{{effects=Find the shortest, most direct physical route that he is seeking, be it the way into or out of a locale.}}{{materials=A set of divination counters of the sort favoured by the priest--bones, ivory counters, sticks, carved runes, or whatever, costing 1gp that can be reused 100 times}}'},
+ {name:'Fire-Quench',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFire Quench\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation (Reversable)}}{{sphere=Elemental (Fire)}}Specs=[Fire Quench,PRspellL7,1H,Evocation]{{components=V,S}}{{range=[[160]] yards}}{{time=[[1]] round}}{{duration=Instantaneous}}{{aoe=vs. magical [[[2*@{selected|casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||cold)\nor vs. normal [[[4*@{selected|casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||cold)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Fire Quench spell)}}{{reference=PHB p234}}SpellData=[w:Fire Quench,lv:7,sp:10,gp:0,cs:VS,sph:Elemental-Fire]{{effects=Smothers twice the area of effect of a fire storm spell with respect to normal fires, and the normal area of effect with respect to magical fires.}}'},
+ {name:'Fire-Seeds',type:'PRspellL6',ct:'80',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFire Seeds\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration}}{{sphere=Elemental (Fire)}}Specs=[Fire Seeds,PRspellL6,1H,Conjuration]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] round per seed (1 to 8 rounds)}}{{duration=[[@{selected|casting-level}]] turns}}{{aoe=[Acorn Missile](!rounds --target caster|@{selected|token_id}|Fire-Seed-Acorn|[[10*@{selected|casting-level}]]|-1|You have Acorn Missiles as weapons?|all-for-one) or [Berry Incendiaries](!rounds --target caster|@{selected|token_id}|Fire-Seed-Holly-Berry|[[10*@{selected|casting-level}]]|-1|You can place Holly Berry incendiaries and set them off.|all-for-one)}}{{save=[Halves](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Fire Seeds spell)}}{{reference=PHB p227}}SpellData=[w:Fire Seeds,lv:6,sp:80,gp:0.01,cs:VSM,sph:Elemental-Fire]{{effects=Creates special missiles or timed incendiaries that burn with great heat. Two options chosen when the spell is cast.\n**Fire seed missiles:** Turns up to [[4]] acorns into special grenade-like missiles with range 40 yards. Use Acorn Fire Seed as a weapon - if using this spell ask the DM to give you Acorns.\n**Fire seed incendiaries:** Turns up to [[8]] holly berries into special incendiaries. Select berry incendiaries button above and you\'ll be asked each round if you want to place or explode them.}}{{materials=The acorns or berries costing 1cp to source}}'},
+ {name:'Fire-Storm',type:'PRspellL7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFire Storm\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation (Reversable)}}{{sphere=Elemental (Fire)}}Specs=[Fire Storm,PRspellL7,1H,Evocation]{{components=V,S}}{{range=[[160]] yards}}{{time=[[1]] round}}{{duration=[While concentrating](!rounds --target caster|@{selected|token_id}|Wall-of-Fire-PR|99|0|The Fire Storm rages while you concentrate|radioactive)}}{{aoe=[[[2*@{selected|casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||fire)}}{{save=[Halves](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Fire Storm spell)}}{{damage=[2d8 + @{selected|casting-level}](!\\amp#13;\\amp#47;r 2d8+@{selected|casting-level})}}{{reference=PHB p234}}SpellData=[w:Fire Storm,lv:7,sp:10,gp:0,cs:VS,sph:Elemental-Fire]{{effects=The whole area is shot through with sheets of roaring flame that equal a wall of fire spell in effect.}}'},
+ {name:'Fire-Trap',type:'PRspellL2',ct:'100',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFire Trap\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Abjuration,Evocation}}{{sphere=Elemental (Fire)}}Specs=[Fire-Trap,PRspellL2,1H,Abjuration|Evocation]{{components=V,S,M}}{{time=[[1]]turn}}{{range=Touch}}{{duration=Permanent until Discharged}}{{aoe=Object touched}}{{save=[Half damage](!\\amp#13;\\amp#47;gmroll 1d20 Save vs. Fire spell)}}{{reference=PHB p204}}SpellData=[w:Fire-Trap,lv:2,sp:100,gp:0.1,cs:VSM,sph:Elemental-Fire]{{effects=Any closeable item can be warded. When discharged, explodes to [[5]]ft radius from the spell\'s center; Damage is [1d4+@{selected|casting-level}](!\\amp#13;\\amp#47;r 1d4+@{selected|casting-level} HP dmg from Fire Trap) HP, or save to half (round up). The item trapped is not harmed by this explosion.}}{{materials=The material components are holly berries, costing 1sp to preserve for use}}'},
+ {name:'Flame-Blade',type:'PRspellL2',ct:'4',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFlame Blade\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Evocation}}{{sphere=Elemental (Fire)}}Specs=[Flame-Blade,PRspellL2,1H,Evocation]{{components=V,S,M}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[4+floor(@{selected|Casting-Level}/2)]] rounds}}{{aoe=[[3]]ft long blade}}{{save=None}}{{reference=PHB p205}}{{healing=[Gain Flameblade](!rounds --target caster|@{selected|token_id}|Flame-Blade|[[4+floor(@{selected|Casting-Level}/2)]]|-1|If hit, Flameblade does 1d4+4 dmg, +2 fire dmg|all-for-one)}}SpellData=[w:Flame-Blade,lv:2,sp:4,gp:0.1,cs:VSM,sph:Elemental-Fire]{{effects=Causes a blazing ray of red-hot fire to spring forth from the caster\'s hand, which is wielded as if it were a scimitar.\n**Instructions:** Use the *Gain Flameblade* button above to set the duration marker, then take a *Flame Blade* weapon in hand to wield - if you don\'t have a *Flame Blade* in your weapons list, ask the DM to give it to you. Once taken \'in-hand\' you can wield the *Flame Blade* like any other weapon.\n}}{{materials=The caster\'s holy symbol, and a leaf of sumac (1sp)}}'},
+ {name:'Flame-Strike',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.03',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFlame Strike\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Evocation}}{{sphere=Combat}}Specs=[Flame Strike,PRspellL5,1H,Evocation]{{components=V,S,M}}{{time=[[8]]}}{{range=[[60]] yards}}{{duration=Instantaneous}}{{aoe=[5ft radius x 30ft column](!rounds --aoe @{selected|token_id}|circle|feet|180|10||fire)}}{{save=[Halves](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Flame Strike spell)}}{{reference=PHB p223}}{{damage=[6d8](!\\amp#13;\\amp#47;gmroll 6d8)hp}}SpellData=[w:Flame Strike,lv:5,sp:8,gp:0.03,cs:VSM,sph:Combat]{{effects=A vertical column of fire roars downward in the location called for by the caster. Any creatures within the area of effect sustain 6d8 points of damage, save to halve}}{{materials=A pinch of sulphur costing 3cp}}'},
+ {name:'Flame-Walk',type:'PRspellL3',ct:'5',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFlame Walk\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Fire)}}Specs=[Flame-Walk,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=Touch}}{{duration=[[1+@{selected|casting-level}]]rounds}}{{aoe=Up to [[{{1},{[[@{selected|casting-level}-4]]} }kh1]] Creature(s) touched}}{{save=None}}{{reference=PHB p210}}{{healing=[Take the Heat](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who has asbestos feet?|token_id}|Flame-walk|[[1+@{selected|casting-level}]]|-1|Granted asbestos boots,+2 save vs magic fire+half damage|tread)}}SpellData=[w:,lv:3,sp:5,gp:500,cs:VSM,sph:Elemental-Fire]{{effects=Empowers one or more creatures to withstand nonmagical fires of temperatures up to 2,000 F. (enabling them to walk upon molten lava). It also confers a +2 bonus to saving throws against magical fire and reduces damage from such fires by one-half, even if the saving throw is failed.}}{{materials=The priest\'s holy symbol and at least 500 gp of powdered ruby per affected creature.}}'},
+ {name:'Forbiddance',type:'PRspellL6',ct:'60',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nForbiddance\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Forbiddance,PRspellL6,1H,Protection]{{components=V,S,M}}{{range=[[30]] yards}}{{time=[[6]] rounds}}{{duration=Permanent}}{{aoe=[@{selected|casting-level} x 20 yard cube](!rounds --aoe @{selected|token_id}|rectangle|yards|30|||dark)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Forbiddance spell)}}{{reference=PHB p228}}SpellData=[w:Forbiddance,lv:6,sp:60,gp:0,cs:VSM,sph:Protection]{{effects=Secure a consecrated area from teleportation, plane shifting, and ethereal penetration.}}'},
+ {name:'Free-Action',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFree Action\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration,Enchantment}}{{sphere=Charm}}Specs=[Free-Action,PRspellL4,1H,Abjuration|Enchantment]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=[[@{selected|casting-level}]]turns}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p217}}{{healing=[Act Freely](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Hippie?|token_id}|Free-Action|[[10*@{selected|casting-level}]]|-1|Acting Freely in air and under water - but how are you breathing?|Strong)}}SpellData=[w:,lv:4,sp:7,gp:0.01,cs:VSM,sph:Charm]{{effects=Move and attack normally for the duration of the spell, even under the influence of magic that impedes movement (such as web or slow spells) or while under water.}}{{materials=A leather thong costing 1cp, bound around the arm or similar appendage, which disintegrates when the spell expires}}'},
+ {name:'Gate',type:'PRspellL7',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nGate\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning}}{{sphere=Summoning}}Specs=[Gate,PRspellL7,1H,Conjuration-Summoning]{{components=V,S}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{time=[[5]]}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p234}}SpellData=[w:Gate,lv:7,sp:5,gp:0,cs:VS,sph:Summoning]{{effects=Causes an interdimensional connection between the plane of existence the priest is in and the plane in which dwells a specific being of great power. The result of this connection is that the sought-after being can step through the gate or portal, from its plane to that of the priest.}}'},
+ {name:'Giant-Insect',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nGiant Insect\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Animal}}Specs=[Giant-Insect,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[20 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|40||magic)}}{{duration=Permanent}}{{aoe=1 to 6 insects}}{{save=None}}{{reference=PHB p217}}SpellData=[w:Giant-Insect,lv:4,sp:7,gp:0,cs:VSM,sph:Animal]{{effects=Turn one or more normal-sized insects into larger forms resembling the giant insects described in the Monstrous Manual. \nThe DM will need to alter the Character Sheets for these tokens, or replace them with the right ones...}}{{materials=Priest\'s holy symbol}}'},
+ {name:'Glyph-of-Warding',type:'PRspellL3',ct:'20',charge:'uncharged',cost:'2000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nGlyph of Warding\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Abjuration,Evocation}}{{sphere=Guardian}}Specs=[Glyph-of-Warding,PRspellL3,1H,Abjuration|Evocation]{{components=V,S,M}}{{time=1 round per 5 sq.ft.}}{{range=Touch}}{{duration=Until discharged}}{{aoe=Special}}{{save=None}}{{reference=PHB p210}}SpellData=[w:Glyph-of-Warding,lv:3,sp:20,gp:2000,cs:VSM,sph:Guardian]{{effects=A powerful inscription magically drawn to prevent unauthorized or hostile creatures from passing, entering, or opening. The priest must set the conditions of the ward; typically any creature violating the warded area without speaking the name of the glyph is subject to the magic it stores, unless it saves vs. spell.}}{{materials=The priest traces the glyph with incense, which, if the area exceeds 50 square feet, must be sprinkled with powdered diamond (at least 2,000 gp worth).}}'},
+ {name:'Goodberry',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nGoodberry\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration,Evocation}}{{sphere=Plant}}Specs=[Goodberry,PRspellL2,1H,Alteration|Evocation]{{components=V,S,M}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[1+@{selected|Casting-Level}]] days}}{{aoe=[2d4](!\\amp#13;\\amp#47;r 2d4) fresh berries}}{{save=None}}{{reference=PHB p205}}{{healing=[[1]]HP per berry}}SpellData=[w:Goodberry,lv:2,sp:10,gp:0,cs:VSM,sph:Plant]{{effects=Either [[1]] berry is equivalent of a full meal, or heals [[1]] HP of damage up to max [[8]] per [[24]] hours.}}{{materials=the caster\'s holy symbol passed over the freshly picked, edible berries to be enspelled (blueberries, blackberries, raspberries, currants, gooseberries, etc.).}}'},
+ {name:'Hallucinatory-Forest',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHallucinatory Forest\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Illusion/Phantasm}}{{sphere=Plant}}Specs=[Hallucinatory-Forest,PRspellL4,1H,Illusion-Phantasm]{{components=V,S}}{{time=[[7]]}}{{range=[[80]]yds}}{{duration=Permanent}}{{aoe=[[[40*@{selected|casting-level}]]sq.ft.](!rounds --aoe @{selected|token_id}|rectangle|feet|240|||green)}}{{save=None}}{{reference=PHB p218}}SpellData=[w:Hallucinatory-Forest,lv:4,sp:7,gp:0,cs:VS,sph:Plant]{{effects=A hallucinatory forest comes into existence, which appears to be perfectly natural and is indistinguishable from a real forest.}}'},
+ {name:'Harm',type:'PRspellL6',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHarm\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Healing}}Specs=[Harm,PRspellL6,1H,Necromancy]{{components=V,S}}{{range=[Touch Attack](!attk --attk-hit @{selected|token_id})}}{{time=[[1]] round}}{{duration=Permanent}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p228}}SpellData=[w:Harm,lv:6,sp:10,gp:0,cs:VS,sph:Healing]{{effects=Infects the victim with a disease and causes loss of all but 1d4 hit points, if a successful touch is inflicted. Cannot harm non-corporeal or nonliving or extra-planar creatures}}'},
+ {name:'Heal',type:'PRspellL6',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHeal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Healing}}Specs=[Heal,PRspellL6,1H,Necromancy]{{components=V,S}}{{range=Touch}}{{time=[[1]] round}}{{duration=Permanent}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p228}}SpellData=[w:Heal,lv:6,sp:10,gp:0,cs:VS,sph:Healing]{{effects=Wipe away disease and injury in the creature who receives the benefits of the spell}}'},
+ {name:'Heat-Metal',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHeat Metal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Elemental(Fire)}}Specs=[Heat-Metal,PRspellL2,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=[40 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|80||fire|true)}}{{duration=[[7]] rounds}}{{aoe= [[floor(@{selected|Casting-Level}/2)]] man-sized equivalent area of metal}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p205}}{{damage=[Heat it up!](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select who to heat|token_id}|Heat-Metal|7|-1|Metal is heated, doing increasing dmg|lightning-helix)}}SpellData=[w:,lv:2,sp:5,gp:0,cs:VSM,sph:Elemental-Fire]{{effects=Makes ferrous metal very hot but not Elven chain. Magical armour saves vs. magical fire (DMG p38) for no effect.\nRound 1 and 7 uncomfortable.\nRound 2 and 6 [1d4](!\\amp#13;\\amp#47;r 1d4) damage.\nRound 3 / 4 / 5 does [2d4](!\\amp#13;\\amp#47;r 2d4) damage.\n\nIn round 5 must save vs. spell or suffer a disability. Roll [1d3](!\\amp#13;\\amp#47;r 1d3) to determine which: \n[[1]]:hand or foot unusable for [2d4](!\\amp#13;\\amp#47;r 2d4) days \n[[2]]:body totally disabled for [1d4](!\\amp#13;\\amp#47;r 1d4) days\n[[3]]:head-unconscious [1d4](!\\amp#13;\\amp#47;r 1d4) turns\nEffect can be totally removed by 5th level *Heal* spell or normal rest. Flammable materials touching metal smoulder and burn [[1]] round later causing [2d4](!\\amp#13;\\amp#47;r 2d4) damage. Fire resistance (spell/potion/ring) or *Protection from Fire* or *Cold* or *Ice Storm* spell negate as does immersion in water or snow.}}{{materials=A holy symbol and the metal to be heated}}'},
+ {name:'Heroes-Feast',type:'PRspellL6',ct:'100',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHeroes\' Feast\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Evocation}}{{sphere=Creation}}Specs=[Heroes Feast,PRspellL6,1H,Evocation]{{components=V,S,M}}{{range=[[10]] yards}}{{time=[[1]] turn}}{{duration=[[[1]] hour](!rounds --target caster|@{selected|token_id}|Heroes-Feast|60|-1|Put on a feast fit for Heroes|trophy)}}{{aoe=[[@{selected|casting-level}]] feasters}}{{save=None}}{{reference=PHB p228}}{{healing=[Make Heroes](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Heroes-Feast|99|0|Blessed, +1 to attk, immune to fear, hopelessness, panic|angel-outfit)}}SpellData=[w:Heroes Feast,lv:6,sp:100,gp:1,cs:VSM,sph:Creation]{{effects=Bring forth a great feast that serves [[12]] creatures, cures wounds, blesses them and gives other benefits.}}'},
+ {name:'Hold-Animal',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHold Animal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Hold-Animal,PRspellL3,1H,Enchantment-Charm]{{components=V,S}}{{time=[[6]]}}{{range=[[80]]yds}}{{duration=[[2*@{selected|casting-level}]]rounds}}{{aoe=1 to 4 animals in [40ft. cube](!rounds --aoe @{selected|token_id}|square|feet|240|40||magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Hold Animal spell)}}{{reference=PHB p211}}{{damage=[Hold the Animal](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Control which animal?|token_id}|Hold-Animal|[[2*@{selected|casting-level}]]|-1|Held fast on a tight leash|fishing-net)}}SpellData=[w:Hold-Animal,lv:3,sp:6,gp:0,cs:VS,sph:Animal]{{effects=Holds one to four animals rigid. Animals affected are normal or giant-sized mammals, birds, or reptiles, but not monsters such as centaurs, gorgons, harpies, naga, etc. Apes, bears, crocodiles, dogs, eagles, foxes, giant beavers, and similar animals are subject to this spell.}}'},
+ {name:'Hold-Person',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0.05',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHold Person\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Charm}}Specs=[Hold-Person,PRspellL2,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[5]]}}{{range=[[120]] yards}}{{duration=[[2*@{selected|Casting-Level}]] rounds}}{{aoe=[1d4](!\\amp#13;\\amp#47;r 1d4) persons in [20ft. cube](!rounds --aoe @{selected|token_id}|square|feet|360|20||magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p205}}{{damage=[Hold them!](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Hold-Person|[[2*@{selected|Casting-Level}]]|-1|Held|fishing-net)}}SpellData=[w:Hold-Person,lv:2,sp:5,gp:0.05,cs:VSM,sph:Charm]{{effects=Holds [1d4](!\\amp#13;\\amp#47;r 1d4) humanoid creatures man-size or smaller (not undead) rigidly in place (but can do actions that don\'t require motion or speech) but caster can choose to hold fewer. [[3]] or [[4]] get normal saving throw. [[2]] get [[0-1]] penalty. Just [[1]] suffers [[0-2]] penalty. Saves are adjusted for Wisdom. Caster can end at will.}}{{materials=A small, straight piece of iron worth 5cp.}}'},
+ {name:'Hold-Plant',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHold Plant\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Enchantment/Charm}}{{sphere=Plant}}Specs=[Hold-Plant,PRspellL4,1H,Enchantment-Charm]{{components=V,S}}{{time=[[7]]}}{{range=[[80]yds}}{{duration=[[@{selected|casting-level}]]rounds}}{{aoe=[1d4](!\\amp#13;\\amp#47;r 1d4 plants can be held) plants or [40sq.ft.](!rounds --aoe @{selected|token_id}|square|feet|240|40||magic) or [up to 16sq.ft.](!rounds --aoe @{selected|token_id}|square|feet|240|||magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Hold Plant spell)}}{{reference=PHB p218}}SpellData=[w:,lv:4,sp:7,gp:0,cs:VS,sph:Plant]{{effects=Affects vegetable matter as follows: 1) it causes ambulatory vegetation to cease moving; 2) it prevents vegetable matter from entwining, grasping, closing, or growing; 3) it prevents vegetable matter from making any sound or movement that is not caused by wind.}}'},
+ {name:'Holy-Word',type:'PRspellL7',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nHoly Word\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Combat}}Specs=[Holy Word,PRspellL7,0H,Conjuration-Summoning]{{components=V}}{{range=[[0]]}}{{time=[[1]]}}{{duration=Special}}{{aoe=[30ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||light|true)}}{{save=None}}{{reference=PHB p234}}SpellData=[w:Holy Word,lv:7,sp:1,gp:0,cs:V,sph:Combat]{{effects=Creates magic of tremendous power. It drives off evil creatures from other planes, forcing them to return to their own planes of existence, provided the speaker is in his home plane.}}'},
+ {name:'Identify',type:'PRspellL1',ct:'100',charge:'uncharged',cost:'100',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nIdentify\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Wizard}}{{school=Divination}}Specs=[Identify,PRspellL1,1H,Divination]{{components=V, S, M}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=[[1*@{selected|Casting-Level}]] rounds}}{{aoe=[[1*@{selected|Casting-Level}]] items}}{{save=None}}{{reference=PHB p205}}SpellData=[w:,lv:1,sp:100,gp:100,cs:VSM,sph:Divination]{{effects=Unlike PHB no need to prepare item. Can Identify a total of [[@{selected|Casting-Level}]] items or attributes - 1 per round. Touch item to attempt to Identify it which might activate any curse (DMs discretion or item description). DM rolls d100. Chance of learning information is [[[{(10*@{selected|Casting-Level}),90}kl1]]](!\\amp#13;\\amp#47;gmroll 1d100)%.}}'},
+ {name:'Imbue-with-Spell-Ability',type:'PRspellL4',ct:'100',charge:'uncharged',cost:'50',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nImbue With Spell Ability\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Enchantment}}{{sphere=Charm}}Specs=[Imbue-with-Spell-Ability,PRspellL4,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[1]]turn}}{{range=Touch}}{{duration=Until used}}{{aoe=Person touched}}{{save=None}}{{reference=PHB p218}}SpellData=[w:,lv:4,sp:100,gp:50,cs:VSM,sph:Charm]{{effects=Transfer a limited number and selection of his currently memorized spells, and the ability to cast them, to another person, who is a non-spellcaster.}}'},
+ {name:'Insect-Plague',type:'PRspellL5',ct:'100',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nInsect Plague\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Conjuration-Summoning}}{{sphere=Combat}}Specs=[Insect Plague,PRspellL5,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[120]] yards}}{{duration=[[[2*@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Insect-Plague|[[2*@{selected|casting-level}]]|-1|A plague of Insects is attacking at your command|chemical-bolt)}}{{aoe=[180ft x 60ft cloud](!rounds --aoe @{selected|token_id}|rectangle|yards|120|60|20|acid)}}{{save=None}}{{reference=PHB p223}}SpellData=[w:Insect Plague,lv:5,sp:100,gp:0.01,cs:VSM,sph:Combat]{{effects=A horde of creeping, hopping, and flying insects gather and swarm in a thick cloud which obscures vision, limiting it to 10 feet, prevents spellcasting, and inflicts damage.}}{{materials=A few granules of sugar, some kernels of grain, and a smear of fat, costing 1cp in total}}'},
+ {name:'Invisibility-to-Animals',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nInvisibility to Animals\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Animal}}Specs=[Invisibility-to-Animals,PRspellL1,1H,Alteration]{{components=S,M}}{{time=[[4]]}}{{range=Touch}}{{duration=[[10+@{selected|Casting-Level}]] rounds}}{{aoe=[[@{selected|Casting-Level}]] creatures touched}}{{save=Special}}{{reference=PHB p200}}{{healing=[Make Invisible](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a beneficiary|token_id}|Invisibility-to-Animals|[[10+@{selected|Casting-Level}]]|-1|Invisible to animals, no powers + Int\\lt6|half-haze)}}SpellData=[w:Invisibility-to-Animals,lv:1,sp:4,gp:0.01,cs:SM,sph:Animal]{{effects=Totally invisible to normal animals of Intelligence less than 6, inc giant (that have no magic or powers). Attacking reveals that individual}}{{materials=1cp of holly rubbed over the recipient}}'},
+ {name:'Invisibility-to-Undead',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nInvisibility to Undead\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Invisibility-to-Undead,PRspellL1,1H,Abjuration]{{components=V,S,M}}{{time=[[4]]}}{{range=Touch}}{{duration=[[6]] rounds}}{{aoe=Creature touched}}{{save=Special}}{{reference=PHB p200}}{{[Make Invisible](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select a beneficiary|token_id}|Invisibility-to-Undead|6|-1|Invisible to undead of \\lt=4HD, others get save vs spell|half-haze)}}SpellData=[w:Invisibility-to-Undead,lv:1,sp:4,gp:0,cs:VSM,sph:Necromantic]{{effects=Causes affected undead to lose track of and ignore the warded creature for the duration of the spell.}}{{materials=The priest\'s holy symbol}}'},
+ {name:'Know-Alignment',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nKnow Alignment\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Know-Alignment,PRspellL2,1H,Divination]{{components=V,S}}{{time=[[1]] round}}{{range=[10 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||magic|true)}}{{duration=[[1]] turn}}{{aoe=[[1]] creature or object}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p206}}SpellData=[w:Know-Alignment,lv:2,sp:10,gp:0,cs:VS,sph:Divination]{{effects=Exactly read the aura of a creature or an aligned object (unaligned objects reveal nothing).}}'},
+ {name:'LT-Give-Life',type:'',ct:'0',charge:'uncharged',cost:'0',body:'/r [[ {{ [[ {{ ?{How many d8 (min. 4, max (4+(@{selected|casting-level}-5)/2))} },{4}}kh1]]},{[[4+floor((@selected|casting-level}-5)/2)]]}}kl1]]d8'},
+ {name:'Life-Transference',type:'PRspellL3',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLife Transference\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Necromancy}}{{sphere=Necromantic}}Specs=[Life-Transference,PRspellL3,1H,Necromancy]{{components=V,S}}{{time=[[1]]}}{{range=[30 ft.](!rounds --aoe @{selected|token_id}|circle|feet|0|30||magic|true)}}{{duration=Instantaneous}}{{aoe=[[1]] Creature}}{{save=None}}{{healing=[Give life](!magic --display-ability @{selected|token_id}|PR-Spells-DB|LT-Give-Life)}}SpellData=[w:Life-Transference,lv:3,sp:1,gp:0,cs:VS,sph:Necromantic]{{effects=You sacrifice some of your health to mend another creature. You take 4d8 damage + up to 1d8 for every 2 levels above 5th and one creature of your choice that you can see within range regains twice the damage you take.\nThere is no saving throw against the spell. The damage experienced is necrotic. (An item that reduced damage from necrotic spells would work)}}'},
+ {name:'Light',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLight\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Alteration}}{{sphere=Sun}}Specs=[Light,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[4]]}}{{range=[[120]] yards}}{{duration=1 hour + [[@{selected|Casting-Level}]] turns}}{{aoe=[20ft radius globe](!rounds --aoe @{selected|token_id}|circle|feet|360|20||light)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p201}}{{damage=[Blind them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to brighten|token_id}|Light|[[60+(10*@{selected|Casting-Level})]]|-1|Blinded by the Light in eyes, 4 penalty on attk+AC|bleeding-eye)}}SpellData=[w:Light,lv:1,sp:4,gp:0,cs:VS,sph:Sun]{{effects=Equal to torch light. Immobile unless cast on a movable object or creature. If on a creature, magic resistance and save vs. spell applies. Resistance negates, and save means light is centred immediately behind creature. Light on eyes blinds creature giving [[0-4]] on attack and worsening AC by [[4]]. Caster can extinguish at any time. Lights are not cumulative.}}'},
+ {name:'Liveoak',type:'PRspellL6',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLiveoak\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Enchantment}}{{sphere=Plant}}Specs=[Liveoak,PRspellL6,1H,Enchantment]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] turn}}{{duration=[[@{selected|casting-level}]] days}}{{aoe=1 oak tree}}{{save=None}}{{reference=PHB p228}}SpellData=[w:Liveoak,lv:6,sp:100,gp:0,cs:VSM,sph:Plant]{{effects=Charm a healthy oak tree (or other type if the DM allows) to cause it to serve as a protector.}}'},
+ {name:'Locate-Animals-or-Plants',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLocate Animals or Plants\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Divination}}{{sphere=Divination(Animal,Plant)}}Specs=[Locate-Animals-or-Plants,PRspellL1,1H,Divination]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[100+(20*@{selected|Casting-Level})]] yards}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=[[[20*@{selected|Casting-Level}]] x 20 yds long](!rounds --aoe @{selected|token_id}|bolt|yards|[[100+20*@{selected|Casting-Level}]]|[[20*@{selected|Casting-Level}]]|20|magic)}}{{save=Negates}}{{reference=PHB p201}}SpellData=[w:Locate-Animals-or-Plants,lv:1,sp:10,gp:0,cs:VSM,sph:Animal|Plant]{{effects=Find direction \\amp distance of any one type of animal or plant desired.}}{{materials=The caster\'s holy symbol}}'},
+ {name:'Locate-Object',type:'PRspellL3',ct:'100',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLocate Object\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Divination}}{{sphere=Divination}}Specs=[Locate-Object,PRspellL3,1H,Divination]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[[60+(10*@{selected|Casting-Level})]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[60+(10*@{selected|Casting-Level})]]||magic|true)}}{{duration=[[8]] hours}}{{aoe=[[1]] object}}{{save=None}}{{reference=PHB p211}}SpellData=[w:,lv:3,sp:100,gp:0.1,cs:VSM,sph:Divination]{{effects=Helps locate a known or familiar object by casting the spell, slowly turning, and will then sense when they are facing in the direction of the object to be located, provided the object is within range.}}{{materials=A piece of lodestone costing 1sp.}}'},
+ {name:'Lose-the-Path',type:'PRspellL6',ct:'30',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLose the Path\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Divination (Reversable)}}{{sphere=Divination}}Specs=[Lose the Path,PRspellL6,1H,Divination]{{components=V,S,M}}{{range=Touch}}{{time=[[3]] rounds}}{{duration=[[@{selected|casting-level}]] turns}}{{aoe=[1 Creature](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Give GPS to whom?|token_id}|Lose-the-Path|[[10*@{selected|casting-level}]]|-1|Has a *really bad* sense of direction|black-flag)}}{{save=None}}{{reference=PHB p227}}SpellData=[w:Find the Path,lv:6,sp:30,gp:0.01,cs:VSM,sph:Divination]{{effects=Makes the creature touched totally lost and unable to find its way for the duration of the spell--although it can be led, of course}}{{materials=A set of divination counters of the sort favoured by the priest--bones, ivory counters, sticks, carved runes, or whatever, costing 1gp which can be reused 100 times}}'},
+ {name:'Lower-Water',type:'PRspellL4',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nLower Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Lower-Water,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[1]]turn}}{{range=[[120]]yds}}{{duration=[[@{selected|casting-level}]]turns}}{{aoe=[Special](!rounds --aoe @{selected|token_id}|square|feet|360|||magic)}}{{save=None}}{{reference=PHB p218}}SpellData=[w:Lower-Water,lv:4,sp:100,gp:0,cs:VSM,sph:Elemental-Water]{{effects=Causes water or similar fluid in the area of effect to sink away to a minimum depth of 1 inch at 2 feet for every experience level of the priest.}}{{materials=The priest\'s holy (or unholy) symbol and a pinch of dust.}}'},
+ {name:'Magic-Font',type:'PRspellL5',ct:'600',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMagic Font\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Magic Font,PRspellL5,1H,Divination]{{components=V,S,M}}{{time=[[1]] hour}}{{range=Touch}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p223}}SpellData=[w:Magic Font,lv:5,sp:600,gp:0,cs:VSM,sph:Divination]{{effects=Causes a holy water font to serve as a scrying device.}}{{materials=The priest\'s holy symbol and the font and its trappings are not consumed by the spell (no cost)}}'},
+ {name:'Magical-Stone',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMagical Stone\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Enchantment}}{{sphere=Combat}}Specs=[Magical-Stone,PRspellL1,1H,Enchantment]{{components=V,S,M}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[[30]] rounds](!rounds --target caster|@{selected|token_id}|Magical-Stone|30|-1|You have 3 magical stones - use them wisely|grenade)}}{{aoe=Up to [[3]] stones}}{{save=None}}{{reference=PHB p201}}{{damage=To use, ensure you have Magical Stones in your MIs (ask DM to give you them) then take them or a sling in hand as a weapon, or give them to another character}}SpellData=[w:Magical-Stone,lv:1,sp:4,gp:0,cs:VSM,sph:Combat]{{effects=Temporarily enchant up to three small pebbles, no larger than sling bullets to then be hurled or slung at an opponent up to [[30]] yards away, and all three can be thrown in one round.}}{{materials=The priest\'s holy symbol and three small pebbles, unworked by tools or magic of any type.}}'},
+ {name:'Magical-Vestment',type:'PRspellL3',ct:'5',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMagical Vestment\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Enchantment}}{{sphere=Protection}}Specs=[Magical-Vestment,PRspellL3,1H,Enchantment]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[0]]}}{{duration=[[5*@{selected|Casting-Level}]] rounds}}{{aoe=The caster}}{{save=None}}{{reference=PHB p211}}{{healing=[Enchant vestment](!rounds --target caster|@{selected|token_id}|Magical-Vestment|[[5*@{selected|Casting-Level}]]|-1|Vestment AC5+[[floor((@{selected|Casting-Level}-5)/3)]]|bolt-shield)}}SpellData=[w:Magical-Vestment,lv:3,sp:5,gp:10,cs:VSM,sph:Protection]{{effects=This spell enchants the caster\'s vestment, providing protection at least the equivalent of chain mail (AC 5) +1 enchantment for each three levels of the priest beyond 5th level, to a maximum of AC 1.}}{{materials=The vestment to be enchanted, costing at least 100gp and can be used 20 times, and the priest\'s holy symbol}}'},
+ {name:'Meld-into-Stone',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMeld Into Stone\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Earth)}}Specs=[Meld-into-Stone,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[6]]}}{{range=[[0]] }}{{duration=8 rounds + 1d8}}{{aoe=The Caster}}{{save=None}}{{reference=PHB p211}}{{healing=[Meld away](!rounds --target caster|@{selected|token_id}|Meld-into-stone|\\amp#91;[80+10*(\\amp#91;[1d8]\\amp#93;\\amp#41;]\\amp#93;|-10|Melded in stone|White-tower)}}SpellData=[w:Meld-into-Stone,lv:3,sp:6,gp:0,cs:VSM,sph:Elemental-Earth]{{effects=Meld the caster\'s body and possessions into a single block of stone, which must be large enough to accommodate his body in all three dimensions.}}{{materials=The stone wall}}'},
+ {name:'Messenger',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMessenger\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Messenger,PRspellL2,1H,Enchantment-Charm]{{components=V,S}}{{time=[[10]]}}{{range=[[[20*@{selected|Casting-Level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[20*@{selected|Casting-Level}]]||red)}}{{duration=[[@{selected|Casting-Level}]]days}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p206}}SpellData=[w:Messenger,lv:2,sp:10,gp:0,cs:VS,sph:Animal]{{effects=This spell enables the priest to call upon a tiny (size T) creature of at least animal intelligence to act as his messenger.}}'},
+ {name:'Moonbeam',type:'PRspellL5',ct:'7',charge:'uncharged',cost:'50',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nMoonbeam\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Evocation, Alteration}}{{sphere=Sun}}Specs=[Moonbeam,PRspellL5,1H,Evocation|Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[60+(10*@{selected|casting-level})]] yards}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Moonbeam|@{selected|casting-level}|-1|Casting a moonbeam|half-haze)}}{{aoe=[5ft radius + Special](!rounds --movable-aoe @{selected|token_id}|circle|feet|[[180+(30*@{selected|casting-level})]]|10||light)}}{{save=None}}{{reference=PHB p223}}SpellData=[w:Moonbeam,lv:5,sp:7,gp:50,cs:VSM,sph:Sun]{{effects=Cause a beam of soft, pale light to strike down from overhead and illuminate whatever area the caster is pointing at. The light is exactly the same as moonlight, so that colors other than shades of black, gray, or white are vague.}}{{materials=Several seeds of any moonseed plant and a piece of opalescent feldspar (moonstone) costing 50gp}}'},
+ {name:'Negative-Plane-Protection',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nNegative Plane Protection\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Negative-Plane-Protection,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] turns, negates 1 attack}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p212}}{{healing=[Protect them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to protect|token_id}|Negative-Plane-Protection|[[10*@{selected|Casting-Level}]]|-1|Save to negate 1 energy drain attack, fail=dmg*2|white-tower)}}SpellData=[w:Negative-Plane-Protection,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Affords partial protection from undead monsters with Negative Energy plane connections (such as shadows, wights, wraiths, spectres, or vampires) and certain weapons and spells that drain energy levels, granting a protected creature a [saving throw](!\\amp#13;\\amp#47;gmroll 1d20 Save vs. Death Magic) vs. death magic. Success means it suffers only normal HP damage, and an attacking undead creature suffers [2d6](!\\amp#13;\\amp#47;r 2d6 damage to the undead) HP; a draining wizard or weapon receives no damage. Proof against only one such attack, whether successful or not. If failed to save, recipient suffers ***double the usual physical damage***, in addition to the loss of experience or Strength that normally occurs.}}'},
+ {name:'Neutralise-Poison',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nNeutralise Poison\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Healing}}Specs=[Neutralise-Poison,PRspellL4,1H,Necromancy]{{components=V,S}}{{time=[[7]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature touched or [[@{selected|Casting-Level}/2]] cu.ft. of substance}}{{save=None}}{{reference=PHB p219}}SpellData=[w:Neutralise-Poison,lv:4,sp:7,gp:0,cs:VS,sph:Healing]{{effects=Detoxifies any venom in creature or substance touched. To remove Poison from an unwilling creature (such as a poisonous snake) needs a \'to hit\' roll.}}'},
+ {name:'Obscure-Object',type:'PRspellL3',ct:'100',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nObscure Object\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Divination}}{{sphere=Divination}}Specs=[Obscure-Object,PRspellL3,1H,Divination]{{components=V,S,M}}{{time=[[1]] turn}}{{duration=[[8]] hours}}{{aoe=[[1]] object}}{{save=None}}{{reference=PHB p211 (reverse of *Locate Object*)}}{{range=[[[60+(10*@{selected|Casting-Level})]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[120+20*@{selected|Casting-Level}]]||dark|true)}}SpellData=[w:,lv:3,sp:100,gp:0.1,cs:VSM,sph:Divination]{{effects=Hides an object from location by spell, crystal ball, or similar means for eight hours.}}{{materials=A piece of lodestone, costing 1sp.}}'},
+ {name:'Obscurement',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nObscurement\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Weather}}Specs=[Obscurement,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=[[4*@{selected|Casting-Level}]]rounds}}{{aoe=10ft high by [[[10*@{selected|Casting-Level}]]ft.sq](!rounds --aoe @{selected|token_id}|square|feet|0|[[10*@{selected|Casting-Level}]]||light|true)}}{{save=None}}{{reference=PHB p206}}SpellData=[w:Obscurement,lv:2,sp:5,gp:0,cs:VS,sph:Weather]{{effects=Causes a misty vapor to arise around the caster, which persists for four rounds per caster level and reduces the visibility ranges of all types of vision (including infravision) to [2d4 feet](!\\amp#13;\\amp#47;r 2d4).}}'},
+ {name:'Part-Water',type:'PRspellL6',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPart Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Elemental (Water)}}Specs=[Part Water,PRspellL6,1H,Alteration]{{components=V,S,M}}{{range=[[20*@{selected|casting-level}]] yards}}{{time=[[1]] turn}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Part-Water|[[10*@{selected|casting-level}]]|-1|The water has parted for you|stopwatch)}}{{aoe=[[3*@{selected|casting-level}]]ft deep x [[[60*@{selected|casting-level}]]ft long x 30 yards wide](!rounds --aoe @{selected|token_id}|rectangle|feet|[[30*@{selected|casting-level}]]|[[60*@{selected|casting-level}]]|90|magic)}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Part Water,lv:6,sp:100,gp:0,cs:VSM,sph:Elemental-Water]{{effects=Cause water or similar liquid to move apart, thus forming a trough.}}'},
+ {name:'Pass-Plant',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPass Plant\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Pass Plant,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p223}}SpellData=[w:Pass Plant,lv:5,sp:8,gp:0,cs:VSM,sph:Plant]{{effects=Enter a tree and move from inside it to inside another tree in approximately the direction desired by the spell user, and must be within the range shown in the table on PHB p223.}}'},
+ {name:'Pass-without-trace',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPass Without Trace\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Enchantment/Charm}}{{sphere=Plant}}Specs=[Pass-Without-Trace,PRspellL1,1H,Enchantment]{{components=V,S,M}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] turns}}{{aoe=[[@{selected|Casting-Level}]] creatures touched}}{{save=None}}{{reference=PHB p201}}{{damage=[Pass without trace](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select to make sneaky|token_id}|Pass-Without-Trace|[[10*@{selected|Casting-Level}]]|-1|Only leave a slight magical trail|ninja-mask)}}SpellData=[w:Pass-Without-Trace,lv:1,sp:10,gp:0,cs:VSM,sph:Plant]{{effects=Leave no physical trace but a magical trail for [1d6](!\\amp#13;\\amp#47;r 1d6) turns.}}{{materials=a sprig of pine or evergreen, which must be burned and the ashes powdered and scattered when the spell is cast}}'},
+ {name:'Plane-Shift',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPlane Shift\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration}}{{sphere=Astral}}Specs=[Plane Shift,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch [Attack if unwilling](!attk --attk-hit @{selected|token_id})}}{{duration=Permanent}}{{aoe=1 creature (Special)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saves vs. Plane Shift spell)}}{{reference=PHB p224}}SpellData=[w:Plane Shift,lv:5,sp:8,gp:1,cs:VSM,sph:Astral]{{effects=Moves the caster or some other creature to another plane of existence. The recipient of the spell remains in the new plane until sent forth by some like means.}}{{materials=A small, forked metal rod costing 10gp to make, that can be used 10 times}}'},
+ {name:'Plant-Door',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPlant Door\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Plant-Door,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch to create a path 8ft high by [[[12*@{selected|casting-level}]]ft x 4ft](!rounds --aoe @{selected|token_id}|bolt|feet|0|[[12*@{selected|casting-level}]]|4|magic)}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p219}}SpellData=[w:Plant-Door,lv:4,sp:7,gp:0.01,cs:VSM,sph:Plant]{{effects=Opens a magical portal or passageway through trees, undergrowth, thickets, or any similar growth--even growth of a magical nature, or enter a solid tree trunk and remain hidden there until the spell ends. If the caster opts to [stay within an oak](!rounds --target caster|@{selected|token_id}|Plant-Door|[[90*@{selected|casting-level}]]|-1|Hiding in an Oak tree|ninja-mask), the spell lasts nine turns per level of the caster; if [within an ash tree](!rounds --target caster|@{selected|token_id}|Plant-Door|[[30*@{selected|casting-level}]]|-1|Hiding in an Oak tree|ninja-mask), it lasts three turns per level. [Otherwise](!rounds --target caster|@{selected|token_id}|Plant-Door|[[10*@{selected|casting-level}]]|-1|Hiding in an Oak tree|tread), the duration of the spell is one turn per level.}}{{materials=A piece of charcoal and the caster\'s holy symbol costing 1cp.}}'},
+ {name:'Plant-Growth',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPlant Growth\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Plant-Growth,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[1]]round}}{{range=[[160]]yds }}{{duration=Permanent}}{{aoe=[An entangled thicket](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||acid) or encourage growth in 1sq.mile}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs spell as caster)}}{{reference=PHB p212}}SpellData=[w:Plant-Growth,lv:3,sp:10,gp:0,cs:VSM,sph:Plant]{{effects=Choose either of two different uses.\n[[1]].Cause normal vegetation to grow, entwine, and entangle to form a thicket or jungle that creatures must hack or force a way through at a movement rate of 10 feet per round (or 20 feet per round for larger-than-man-sized creatures).\n[[2]].Or affect a one-mile square area to render plants more vigorous, fruitful, and hardy, increasing yields by 20% to 50% ([1d4+1] x 10%), given a normal growing season. The DM secretly makes a saving throw (based on the caster\'s level) to see if the spell takes effect.}}{{materials=Plants in the area of effect}}'},
+ {name:'Poison',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPoison\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Necromancy (reversable)}}{{sphere=Healing}}Specs=[Poison,PRspellL4,1H,Necromancy]{{components=V,S}}{{time=[[7]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creature touched or [[@{selected|Casting-Level}/2]] cu.ft. of substance}}{{save=None}}{{reference=PHB p219 (reverse Neutralise Poison)}}{{damage=[Try to Touch](~selected|To-Hit-Spell)}}SpellData=[w:Poison,lv:4,sp:7,gp:0,cs:VS,sph:Healing]{{effects=Introduces venom in creature or substance touched. Requires an attack roll and subject gets a saving throw, if that fails subject is incapacitated and dies in [[1]] turn.}}\n!magic --touch @{selected|token_id}|Poison|10|-1|Poisoned, counting down to Death|skull'},
+ {name:'Prayer',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPrayer\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Conjuration/Summoning}}{{sphere=Combat}}Specs=[Prayer,PRspellL3,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[6]]}}{{range=[[0]]}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=[60ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|120||light|true)}}{{save=None}}{{reference=PHB p212}}SpellData=[w:Prayer,lv:3,sp:6,gp:1,cs:VSM,sph:Combat]{{healing=Select *[Friends]* button below and target all your friends, then select the *[Enemies]* button below and target your enemies}}{{effects=Affects all in the area of the spell. [Friends](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Prayer-ally|[[@{selected|Casting-Level}]]|-1|Prayer, [[+1]] on attack, dmg + saves|angel-outfit) get +[[1]] benefit on all attack, damage and saves. All [Enemies](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Prayer-foe|[[@{selected|Casting-Level}]]|-1|Prayer foe, [[-1]] on attack, dmg + saves|radioactive) in area at time of cast get [[0-1]] penalty. Once cast priest can do other things. If another priest of same religious persuasion (not just alignment) is *Chanting* at the same time, get +[[2]] and [[0-2]]}}{{materials=Silver holy symbol, prayer beads, or similar device, costing 10sp.}}'},
+ {name:'Preserve-Life',type:'PRspellL0',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPreserve Life\nas a level @{selected|Casting-Level} caster}}{{splevel=Special}}{{school=Healing,Necromantic}}{{sphere=Necromantic}}Specs=[Preserve-Life,PRspellL0,1H,Necromantic]{{components=V,S}}{{time=[[5]]}}{{range=[30 ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||light|true)}}{{duration=Permanent}}{{aoe=Creatures in 30ft radius}}{{save=None}}{{healing=distribute [[5*@{selected|Casting-Level}]] HP curing over selected creatures}}SpellData=[w:,lv:0,sp:5,gp:0,cs:VS,sph:Healing]{{effects=At Second level a Priest of Life (a Healer) gets a special ability **Preserve Life**. A Healer can spend five times his level in healing points over specific characters within 30ft, however this cannot raise a character to more than half their normal hit points. This can be done a number of times a day equal to their level.}}'},
+ {name:'Produce-Fire',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProduce Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Elemental(Fire)}}Specs=[Produce-Fire,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[40]]yds}}{{duration=[[1]]round}}{{aoe=[12sq.ft.](!rounds --aoe @{selected|token_id}|square|feet|120|12||fire)}}{{save=None}}{{reference=PHB p219}}SpellData=[w:,lv:4,sp:7,gp:0.1,cs:VSM,sph:Elemental-Fire]{{effects=Creates a common fire of up to 12 feet per side in area.}}{{materials=A paste of sulfur and wax costing 10cp to produce, formed into a ball and thrown at the target.}}'},
+ {name:'Produce-Flame',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProduce Flame\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Elemental (Fire)}}Specs=[Produce-Fire,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[40]] yards}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=3ft diameter pool of fire when thrown}}{{save=None}}{{reference=PHB p206}}{{damage=[Create Flames](!rounds --target caster|@{selected|token_id}|Produce-Flame|@{selected|casting-level}|-1|Able to create little fire bombs|three-leaves)\n[1d4+1](!\\amp#13;\\amp#47;r 1d4+1 fire damage and if catch fire spend a round putting it out or suffer more damage) if struck}}SpellData=[w:Produce-Flame,lv:2,sp:5,gp:0,cs:VS,sph:Elemental-Fire]{{effects=A bright flame, equal in brightness to a torch, springs forth from the caster\'s palm which does not harm the caster, but it is hot and it causes the combustion of flammable materials (paper, cloth, dry wood, oil, etc.). Can be hurled as a missile which flashes on impact, igniting combustibles within a 3-foot diameter of its centre of impact, and then it goes out.}}\n!magic --touch @{selected|token_id}|Produce-flame-on-fire|99|0|On fire and takes 1d4+1 HP damage|lightning-helix)'},
+ {name:'Protection-From-Good-10ft',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProtection from Good, 10ft radius\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Protection-from-Good-10ft,PRspellL4,1H,Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] turns}}{{aoe=[[10]]ft radius}}{{save=None}}{{healing=[Protect them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Prot-from-Good-10ft|[[10*@{selected|Casting-Level}]]|-1|2 bonus vs good attk+save, block control, block attk by conjured+x-planar|white-tower)}}{{reference=PHB p219}}SpellData=[w:Protection-from-Good-10ft,lv:4,sp:7,gp:0,cs:VSM,sph:Protection]{{effects=Identical in all respects to that of a *protection from good* spell, except that it encompasses a much larger area and its duration is greater.}}{{materials=A circle 20 feet in diameter using unholy water and smouldering dung (found for free), according to the protection from good spell}}'},
+ {name:'Protection-from-Evil',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProtection from Evil\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Protection-from-Evil,PRspellL1,1H,Abjuration]{{components=V,S,M}}{{time=[[4]]}}{{range=Touch}}{{duration=[[3*@{selected|Casting-Level}]] rounds}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p201}}{{healing=[Protect them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Protection-from-Evil|[[3*@{selected|Casting-Level}]]|-1|2 bonus vs evil attk+save, block control, block attk by conjured+x-planar|white-tower)}}SpellData=[w:Protection-from-Evil,lv:1,sp:4,gp:0.1,cs:VSM,sph:Protection]{{effects=Creates a magical barrier around the recipient at a distance of 1 foot. The barrier moves with the recipient and has three major effects:\n[[1]]: attacks by evil or evilly enchanted creatures are at -2 and saves have a +2 bonus.\n[[2]]: mental control over the protected creature or invading and taking over its mind is blocked.\n[[3]]: prevents bodily contact by creatures of an extraplanar or conjured nature.\nEnds if the protected character makes a melee attack against or tries to force the barrier against the blocked creature.}}{{materials=Holy water or burning incense costing 1sp}}'},
+ {name:'Protection-from-Evil-10ft',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProtection from Evil, 10ft radius\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Protection-from-Evil-10ft,PRspellL4,1H,Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] turns}}{{aoe=[[10]] ft radius}}{{save=None}}{{reference=PHB p219}}{{healing=[Protect them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Prot-from-Evil-10ft|[[10*@{selected|Casting-Level}]]|-1|2 bonus vs evil attk+save, block control, block attk by conjured+x-planar|white-tower)}}SpellData=[w:Protection-from-Evil-10ft,lv:4,sp:7,gp:0.5,cs:VSM,sph:Protection]{{effects=The globe of protection of this spell is identical in all respects to that of a *protection from evil* spell, except that it encompasses a much larger area and its duration is greater. Effect moves with the creature touched.}}{{materials=Trace a circle 20 feet in diameter using 5sp-worth of holy water and incense, according to the *protection from evil* spell.}}'},
+ {name:'Protection-from-Fire',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProtection from Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Abjuration}}{{sphere=Protection,Elemental(Fire)}}Specs=[Protection-from-Fire,PRspellL3,1H,Abjuration]{{components=V,S,M}}{{time=[[6]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] turns (max)}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p212}}{{healing=[Protect them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Protection-from-Fire|[[10*@{selected|Casting-Level}]]|-1|Immune to normal fire. If caster, absorbs 12*@{selected|Casting-Level} HP magic fire dmg|white-tower)}}SpellData=[w:Protection-from-Fire,lv:3,sp:6,gp:0,cs:VSM,sph:Protection|Elemental-Fire]{{effects=*If cast on caster:* totally immune to normal fires of all types. Absorbs [[12*@{selected|Casting-Level}]] HP damage from all magical fires then dispelled. *If cast on another creature:* immune to ordinary fire. +[[4]] on saving throws against magical fire and [[50]]% damage ([[25]]% if save).}}{{materials=Caster\'s holy symbol.}}'},
+ {name:'Protection-from-Lightning',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nProtection from Lightning\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration}}{{sphere=Protection,Weather)}}Specs=[Protection-from-Lightning,PRspellL4,1H,Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=Special}}{{aoe=[[1]] creature}}{{save=None}}{{reference=PHB p219}}SpellData=[w:Protection-from-Lightning,lv:4,sp:7,gp:0,cs:VSM,sph:Protection|Weather]{{effects=Depends on who it is cast upon.\n**If cast upon the [Caster](!rounds --target caster|@{selected|token_id}|Prot-caster-vs-Lightning|[[10*@{selected|Casting-Level}]]|-1|Immune to electrical dmg. Absorbs [[10*@{selected|Casting-Level}]] HP electrical dmg|white-tower)**, confers complete invulnerability to electrical attack until has absorbed [[10*@{selected|casting-level}]] HP of electrical damage.\n**If cast upon [Another creature](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Prot-vs-Lightning|[[10*@{selected|Casting-Level}]]|-1|+[[4]] on saves vs electrical dmg + dmg is halved|white-tower)**, gives a save bonus of +4 vs. electrical attacks, and reduces damage by 50%.}}{{materials=Caster\'s holy symbol.}}'},
+ {name:'Purify-Food-and-Drink',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPurify Food and Drink\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration (reversable)}}{{sphere=All}}Specs=[Purify-Food-and-Drink,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[1]] round}}{{range=[[30]] yds}}{{duration=Permanent}}{{aoe=[[@{selected|Casting-Level}]] cu.ft.}}{{save=None}}{{reference=PHB p202}}SpellData=[w:Purify-Food-and-Drink,lv:1,sp:10,gp:0,cs:VS,sph:All]{{effects=Makes spoiled, rotten, poisonous, or otherwise contaminated food and water pure and suitable for eating and drinking.}}'},
+ {name:'Putrify-Food-and-Drink',type:'PRspellL1',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPutrify Food and Drink\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration (reversable)}}{{sphere=All}}Specs=[Putrify-Food-and-Drink,PRspellL1,1H,Alteration]{{components=V,S}}{{time=[[1]] round}}{{range=[[30]] yds}}{{duration=Permanent}}{{aoe=[[@{selected|Casting-Level}]] cu.ft.}}{{save=None}}{{reference=PHB p202 (reverse of *Purify Food \\amp Drink*)}}SpellData=[w:Putrify-Food-and-Drink,lv:1,sp:10,gp:0,cs:VS,sph:All]{{effects=Makes pure food and water into spoiled, rotten, poisonous, or otherwise contaminated food and water totally unsuitable for eating and drinking.}}'},
+ {name:'Pyrotechnics',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nPyrotechnics\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Fire)}}Specs=[Pyrotechnics,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[6]]}}{{range=[[160]]yds }}{{duration=Special}}{{aoe=10x or 100x fire source}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs Pyrotechnics spell)}}{{reference=PHB p212}}SpellData=[w:Pyrotechnics,lv:3,sp:6,gp:0,cs:VSM,sph:Elemental-Fire]{{effects=Draws on an existing fire source to produce either of two effects, at the option of the caster.\n[[1]]: produce coloured aerial fireworks that [Blinds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who\'s blinded by fireworks?|token_id}|Pyro-blinded|[[1+([[1d4]])]]|-1|Blinded by bright flashes, AC \\amp Attack at -4|bleeding-eye) creatures in, under, or within [120 feet](!rounds --aoe @{selected|token_id}|circle|feet|480|120||light) that have an unobstructed line of sight to the effect for 1d4+1 rounds (save vs. spell to negate).\n[[2]]: cause a thick, writhing stream of smoke to arise from the source and form a [Choking cloud](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who\'s choking in smoke?|token_id}|Pyro-smoke|[[@{selected|casting-level}]]|-1|Choking in smoke, and only 2ft vision|bleeding-eye) for [[@{selected|casting-level}]] rounds covering a roughly hemispherical volume from the ground or floor up totally obscuring vision beyond 2 feet. Fills a volume [100 times the fire source](!rounds --aoe @{selected|token_id}|circle|feet|480|||black).}}{{materials=Fire source}}'},
+ {name:'Quench-Fire',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nQuench Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration (reversable)}}{{sphere=Elemental(Fire)}}Specs=[Quench-Fire,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[40]]yds}}{{duration=[[1]]round}}{{aoe=[12sq.ft.](!rounds --aoe @{selected|token_id}|square|feet|120|12||cold)}}{{save=None}}{{reference=PHB p219 (reverse of *Produce Fire*)}}SpellData=[w:Quench-Fire,lv:4,sp:7,gp:0.1,cs:VSM,sph:Elemental-Fire]{{effects=*Quench fire* extinguishes any normal fire (coals, oil, tallow, wax, wood, etc.) within the area of effect.}}{{materials=A paste of sulphur and wax costing 1sp to prepare, formed into a ball and thrown at the target.}}'},
+ {name:'Quest',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nQuest\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Enchartment-Charm}}{{sphere=Charm}}Specs=[Quest,PRspellL5,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[8]]}}{{range=[[[60]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|120||magic|true)}}{{duration=Until Fulfilled}}{{aoe=1 creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saves vs. Quest spell)}}{{reference=PHB p224}}SpellData=[w:Quest,lv:5,sp:8,gp:0,cs:VSM,sph:Charm]{{effects=Require the affected creature to perform a service and return to the priest with proof that the deed was accomplished.}}{{materials=The priest\'s holy symbol}}'},
+ {name:'Rainbow',type:'PRspellL5',ct:'7',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRainbow\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Evocation, Alteration}}{{sphere=Weather, Sun}}Specs=[Rainbow,PRspellL5,1H,Evocation|Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[[120]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|240||magic|true)}}{{duration=[[[@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Rainbow|@{selected|casting-level}|-1|The lovely rainbow is still working for you|stopwatch)}}{{aoe=Special}}{{save=None}}{{reference=PHB p224}}SpellData=[w:Rainbow,lv:5,sp:7,gp:1000,cs:VSM,sph:Weather|Sun]{{effects=Two applications:\n**Bow:** Creates a shimmering, multi-layered short composite bow of rainbow hues, with 7 missiles each a +2 weapon described in the table on PHB p 224. To use this spell, add a Rainbow-Bow and 7 Rainbow-Sheaf-Arrows to your bag and use them as weapons.\n**Bridge:** Causes the rainbow to form a seven-hued bridge up to 3 feet wide per level of the caster.}}{{materials=The priest\'s holy symbol, a vial of holy water, and either a rainbow or a diamond of not less than 1,000 gp value, specially prepared with bless and prayer spells while in sight of a rainbow}}'},
+ {name:'Raise-Dead',type:'PRspellL5',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRaise Dead\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Raise Dead,PRspellL5,1H,Necromancy]{{components=V,S}}{{time=[[1]] round}}{{range=[[[30]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saves vs. Raise Dead spell)}}{{reference=PHB p224}}SpellData=[w:Raise Dead,lv:5,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Restore life to a dwarf, gnome, half-elf, halfling, or human (other creatures may be allowed, at the DM\'s option).}}{{materials=The priest\'s holy symbol}}'},
+ {name:'Raise-Water',type:'PRspellL4',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRaise Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration (reversable)}}{{sphere=Elemental(Water)}}Specs=[Raise-Water,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[1]]turn}}{{range=[[120]]yds}}{{duration=[[@{selected|casting-level}]]turns}}{{aoe=Special}}{{save=None}}{{reference=PHB p218 (reverse of *Lower Water*)}}SpellData=[w:Raise-Water,lv:4,sp:100,gp:0,cs:VSM,sph:Elemental-Water]{{effects=*Raise Water* causes water or similar fluids to return to their highest natural level: spring flood, high tide, etc. }}{{materials=The priest\'s holy (or unholy) symbol and a pinch of dust.}}'},
+ {name:'Reflecting-Pool',type:'PRspellL4',ct:'1200',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nReflecting Pool\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Reflecting-Pool,PRspellL4,1H,Divination]{{components=V,S,M}}{{time=[[2]] hours}}{{range=[[10]] yds}}{{duration=[[@{selected|casting-level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p219}}SpellData=[w:,lv:4,sp:1200,gp:1,cs:VSM,sph:Divination]{{effects=Cause a pool of normal water found in a natural setting to act as a scrying device.}}{{materials=oil extracted from such nuts as the hickory and the walnut, costing 1gp to refine, and dropped in three measures upon the surface of the pool. (A measure need be no more than a single ounce of oil.)}}'},
+ {name:'Remove-Curse',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRemove Curse\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Remove-Curse,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[6]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Special}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p213}}SpellData=[w:Remove-Curse,lv:3,sp:6,gp:0,cs:VS,sph:Protection]{{effects=Usually able to remove a curse on an object, on a person, or in the form of some undesired sending or evil presence.}}'},
+ {name:'Remove-Fear',type:'PRspellL1',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRemove Fear\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest (reversable)}}{{school=Abjuration}}{{sphere=Charm}}Specs=[Remove-Fear,PRspellL1,1H,Abjuration]{{components=V,S}}{{time=[[1]]}}{{range=[10 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||light|true)}}{{duration=[[1]]turn}}{{aoe=[[floor(@{selected|Casting-Level}/4)]] creatures}}{{save=[At +4](!\\amp#13;\\amp#47;gmroll 1d20+4 saving throw)}}{{reference=PHB p202}}{{healing=[Protect Them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select who to make brave|token_id}|Protection|10|-1|Save vs. Fear at +4|white-tower)}}SpellData=[w:Remove-Fear,lv:1,sp:1,gp:0,cs:VS,sph:Charm]{{effects=Instills courage in the spell recipient, raising the creature\'s saving throw rolls against magical fear attacks by +4 for one turn, and grants another save vs. any previous failed save vs. fear, with a +4 bonus to the die roll.}}'},
+ {name:'Remove-Paralysis',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRemove Paralysis\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Remove-Paralysis,PRspellL3,1H,Abjuration]{{components=V,S}}{{time=[[6]]}}{{range=[[10*@{selected|Casting-Level}]]yds}}{{duration=Permanent}}{{aoe=[1d4](!\\amp#13;\\amp#47;r 1d4)creatures in a [20ft cube](!rounds --aoe @{selected|token_id}|square|feet|[[30*@{selected|Casting-Level}]]|20||light)}}{{save=Special}}{{reference=PHB p213}}SpellData=[w:Remove-Paralysis,lv:3,sp:6,gp:0,cs:VS,sph:Protection]{{effects=Free one or more creatures from any paralyzation or from related magic.}}'},
+ {name:'Repel-Insects',type:'PRspellL4',ct:'10',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRepel Insects\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration,Alteration}}{{sphere=Animal,Protection}}Specs=[Repel-Insects,PRspellL4,1H,Abjuration|Alteration]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[0]]}}{{duration=[[@{selected|Casting-Level}]] turns}}{{aoe=[[10]]ft radius}}{{save=None}}{{reference=PHB p220}}{{healing=[Apply Repellant](!rounds --target caster|@{selected|token_id}|Repel-Insects|[[10*@{selected|Casting-Level}]]|-1|Repels all natural insects+others\\lt[[floor(@{selected|casting-level}/3)]]HD. Others save to pass with 1d6 dmg|white-tower)}}SpellData=[w:Repel-Insects,lv:4,sp:10,gp:0.01,cs:VSM,sph:Protection|Animal]{{effects=Creates an invisible barrier to all sorts of insects, and normal insects do not approach within 10 feet of the caster while the spell is in effect: giant insects with less than [[floor(@{selected|casting-level}/3)]] Hit Dice are also repelled but insects with more Hit Dice can enter the protected area if the insect is especially aggressive and saves vs. spell - if save, can pass but take [1d6](!\\amp#13;\\amp#47;r 1d6) damage.}}{{materials=any one of the following, each costing just 1cp: several crushed marigold flowers, a whole crushed leek, seven crushed stinging nettle leaves, or a small lump of resin from a camphor tree.}}'},
+ {name:'Resist-Cold',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nResist Cold\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Protection}}Specs=[Resist-Cold,PRspellL2,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p206}}{{healing=[Grant Resistance](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to Protect|token_id}|Resist-Cold|[[@{selected|Casting-Level}]]|-1|Immune to normal cold, magic cold +3 save + 50 dmg|white-tower)}}SpellData=[w:Resist-Cold,lv:2,sp:5,gp:1,cs:VSM,sph:Protection]{{effects=Complete immunity to mild conditions. Can resist normal cold, and magical cold to gain +[[3]] on saves and [[50]]% damage ([[25]]% if save) from e.g. frostbrand swords, ice storms, wand of frost, or white dragon\'s breath}}{{materials=A drop of mercury, a rare \'magical\' liquid metal costing 1gp a drop}}'},
+ {name:'Resist-Fire',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nResist Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Protection}}Specs=[Resist-Fire,PRspellL2,1H,Alteration]{{components=V,S,M}}{{time=[[5]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p206}}{{healing=[Grant Resistance](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select the fireman|token_id}|Resist-Fire|[[@{selected|Casting-Level}]]|-1|Immune to normal fire, magic fire +3 save + 50% dmg|white-tower)}}SpellData=[w:Resist-Fire,lv:2,sp:5,gp:1,cs:VSM,sph:Protection]{{effects=Complete immunity to mild conditions. Can resist normal fire, and magical fire to gain +[[3]] on saves and [[50]]% damage ([[25]]% if save) from e.g. burning oil or fireball or flaming swords or fire storm or meteors or red dragon breath.}}{{materials=A drop of mercury, a rare \'magical\' liquid metal costing 1gp a drop}}'},
+ {name:'Reverse-Tongues',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nReverse Tongues\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Divination}}Specs=[Reverse Tongues,PRspellL4,1H,Alteration]{{components=V,S}}{{time=[[7]]}}{{range=[[0]]}}{{duration=[[1]] turn}}{{aoe=[Hearing range - 60ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|120||magic|true)}}{{save=None}}{{damage=[Speak in Tongues](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Speak Gobbledegook|token_id}|PR-Reverse-Tongues|10|-1|Do not understand - reverse Tongues|Edge-crack)}}{{reference=PHB p220}}SpellData=[w:Tongues,lv:4,sp:7,gp:0,cs:VS,sph:Divination]{{effects=This spell cancels the effect of the *tongues* spell or confuses verbal communication of any sort within the area of effect.}}'},
+ {name:'Sanctuary',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSanctuary\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Sanctuary,PRspellL1,1H,Abjuration]{{components=V,S,M}}{{time=[[4]]}}{{range=Touch}}{{duration=[[2+@{selected|Casting-Level}]] rounds}}{{aoe=Creature touched}}{{save=None}}{{reference=PHB p202}}{{healing=[Grant Sanctuary](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who gets Sanctuary|token_id}|Sanctuary|[[2+@{selected|Casting-Level}]]|-1|Can\'t attk, foes save or can\'t hit|white-tower)}}SpellData=[w:Sanctuary,lv:1,sp:4,gp:0.1,cs:VSM,sph:Protection]{{effects=Any opponent attempting to strike or otherwise directly attack the protected creature must save vs. spell to attack normally and be unaffected, otherwise the opponent loses track of and totally ignores the warded creature for the duration of the spell.}}{{materials=The priest\'s holy symbol and a small silver mirror costing 1gp which can be used at least 10 times}}'},
+ {name:'Shillelagh',type:'PRspellL1',ct:'2',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nShillelagh\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Alteration}}{{sphere=Combat,Plant}}Specs=[Shillelagh,PRspellL1,1H,Alteration]{{components=V,S,M}}{{time=[[2]]}}{{range=Touch}}{{duration=[[4+@{selected|Casting-Level}]] rounds}}{{aoe=[[1]]oak club or staff}}{{save=None}}{{reference=PHB p202}}{{healing=[Bless the Club](!rounds --target caster|@{selected|token_id}|Shillelagh|[[4+@{selected|Casting-Level}]]|-1|Club is +1 to-hit, does SM:2 d4 L:1 d4 +1 damage|angel-outfit)}}SpellData=[w:Shillelagh,lv:1,sp:2,gp:0.01,cs:VSM,sph:Combat|Plant]{{effects=Change the caster\'s own oak cudgel or unshod staff into a magical weapon that gains a +1 bonus to its attack roll and inflicts 2d4 points of damage on opponents up to man size, and 1d4+1 points of damage on larger opponents. The spell inflicts no damage to the staff or cudgel. The caster must wield the shillelagh, of course.}}{{materials=A shamrock leaf costing 1cp and the caster\'s holy symbol.}}'},
+ {name:'Shrink-Animal',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nShrink Animal\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest (Reversable)}}{{school=Alteration}}{{sphere=Animal}}Specs=[Shrink Animal,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=[[80]] yards}}{{duration=[[2*@{selected|Casting-Level}]] rounds}}{{aoe=Up to [[8]] creatures in a [20ft. square](!rounds --aoe @{selected|token_id}|square|feet|240|20||magic)}}{{save=None}}{{reference=PHB p221}}{{healing=[Shrink](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which animals to shrink?|token_id}|Shrink-Animal|[[2*@{selected|casting-level}]]|-1|So small - HD/2, HP/2, dmg/2|back-ache)}}SpellData=[w:Shrink Animal,lv:5,sp:8,gp:0.01,cs:VSM,sph:Animal]{{effects=Causes up to eight animals within a 20-foot square area to shrink to half their normal size, halving Hit Dice (with resultant reduction in attack potential), hit points (except hit points added to Hit Dice), and damage in combat. Movement and AC are not affected}}{{materials=The priest\'s holy symbol and a scrap of food, cost 1cp}}'},
+ {name:'Shrink-Insect',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nShrink Insect\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Animal}}Specs=[Shrink-Insect,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[20 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|40||yellow|true)}}{{duration=Permanent}}{{aoe=1 to 6 insects}}{{save=None}}{{reference=PHB p217 (reverse of *Giant Insect*)}}SpellData=[w:Shrink-Insect,lv:4,sp:7,gp:0,cs:VSM,sph:Animal]{{effects=Reduces any giant insect to normal insect size.}}{{materials=Priest\'s holy symbol.}}'},
+ {name:'Silence-15ft-radius',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSilence 15ft radius\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Guardian)}}Specs=[Silence-15ft-radius,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[120]] yards}}{{duration=[[2*@{selected|Casting-Level}]] rounds}}{{aoe=[15ft radius sphere](!rounds --aoe @{selected|token_id}|circle|yards|120|10||dark)}}{{save=None}}{{reference=PHB p206}}SpellData=[w:Silence-15ft-radius,lv:2,sp:5,gp:0,cs:VS,sph:Guardian]{{damage=[Silence them](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who should be silenced?|token_id}|Silence-15ft|[[2*@{selected|casting-level}]]|-1|Silenced - no verbalisation possible|ninja-mask)}}{{effects=All sound stopped in affected area: conversation impossible and spells with V components can\'t be cast. Centre stationary unless cast on movable object or creature. Unwilling creature gets save vs. spell and success indicates silence centred behind creature.}}'},
+ {name:'Slay-Living',type:'PRspellL5',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSlay Living\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Slay Living,PRspellL5,1H,Necromancy]{{components=V,S}}{{time=[[1]] round}}{{range=[[[30]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=Permanent}}{{aoe=1 creature}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saves vs. Slay Living spell)}}{{reference=PHB p224}}SpellData=[w:Slay Living,lv:5,sp:10,gp:0,cs:VS,sph:Necromantic]{{effects=Grants the victim a saving throw vs. death magic. If the saving throw is successful, the victim sustains damage equal to that of a *cause serious wounds* spell--i.e., [2d8+1](!\\amp#13;\\amp#47;gmroll 2d8+1) points. Failure means the victim dies instantly}}{{materials=The priest\'s holy symbol}}'},
+ {name:'Slow-Poison',type:'PRspellL2',ct:'1',charge:'uncharged',cost:'0.02',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSlow Poison\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Slow-Poison,PRspellL2,1H,Necromancy]{{components=V,S,M}}{{time=[[1]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]] hours}}{{aoe= Creature touched}}{{save=None}}{{reference=PHB p207}}{{healing=[Slow the poison](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select sufferer|token_id}|Slow-Poison|[[60*@{selected|Casting-Level}]]|-1|Slowed poison, no substantial harm yet|stopwatch)}}SpellData=[w:Slow-Poison,lv:2,sp:1,gp:0.02,cs:VSM,sph:Healing]{{effects=Reduces effect of poison if cast during onset time (DMG p73 table 51). Does not neutralise the poison but stops it substantially harming the victim for duration in hope of finding a cure.}}{{materials=Cleric\'s holy symbol and a clove of garlic costing 2cp to crush and smear on the wound, or eaten for ingested poisons.}}'},
+ {name:'Snake-Charm',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSnake Charm\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Snake-Charm,PRspellL2,1H,Enchantment-Charm]{{components=V,S}}{{time=[[5]]}}{{range=[[30]] yards}}{{duration=Special}}{{aoe=[30ft cube](!rounds --aoe @{selected|token_id}|square|yards|30|10||magic)}}{{save=None}}{{reference=PHB p207}}SpellData=[w:Snake-Charm,lv:2,sp:5,gp:0,cs:VS,sph:Animal]{{effects=Causes one or more snakes to cease all activity except a semi-erect, swaying movement. If charmed while [in a torpor](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Snake-Charm|\\amp#91;[10\\amp#42;\\amp#91;[\\amp#91;[1d4]\\amp#93;+2]\\amp#93;]\\amp#93;|-1|Charmed the snakes, at least for now!|chained-heart), duration of the spell is 1d4+2 turns; if [not torpid](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Snake-Charm|[\\amp#91;[\\amp#91;1d3\\amp#93;]\\amp#42;10\\amp#93;]|-1|Charmed the snakes, at least for now!|chained-heart), the charm lasts 1d3 turns; if the snakes are [angry or attacking](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Snake-Charm|[\\amp#91;[\\amp#91;1d4\\amp#93;]+4\\amp#93;]|-1|Charmed the snakes, at least for now!|chained-heart), the spell lasts 1d4+4 ***rounds***. Can charm snakes whose total HP are less than or equal to those of the priest.}}'},
+ {name:'Snakes-to-Sticks',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSnakes to Sticks\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Animal}}Specs=[Snakes-to-Sticks,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[30]]yds}}{{duration=[[2*@{selected|casting-level}]]rounds}}{{aoe=[1d4](!\\amp#13;\\amp#47;r 1d4) + [[@{selected|casting-level}]] snakes in a [10ft. cube](!rounds --aoe @{selected|token_id}|square|feet|90|10||acid)}}{{save=None}}{{reference=PHB p220 (reverse of *Sticks to Snakes*)}}SpellData=[w:Snakes-to-Sticks,lv:4,sp:7,gp:0.5,cs:VSM,sph:Animal]{{effects=This spell changes normal-sized snakes to sticks, or it negates the *sticks to snakes* spell according to the level of the priest countering the spell.}}{{materials=A small piece of bark and several snake scales, costing 5sp.}}'},
+ {name:'Snare',type:'PRspellL3',ct:'30',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSnare\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Enchantment/Charm}}{{sphere=Plant}}Specs=[Snare,PRspellL3,1H,Enchantment]{{components=V,S,M}}{{time=[[3]] rounds}}{{range=Touch}}{{duration=Permanent until triggered}}{{aoe=[[24+(2*@{selected|Casting-Level}]] inches}}{{save=None}}{{reference=PHB p213}}SpellData=[w:Snare,lv:3,sp:30,gp:0.5,cs:VSM,sph:Plant]{{effects=Snare is 90% undetectable without magic, will tighten on limb or neck. If attached to tree, will bend \\amp spring \\amp does [1d6](!\\amp#13;\\amp#47;r 1d6) damage (\\amp strangle if neck). [[23]] strength to break in 1st hour, [[1]] less per hour for [[6]] hours ([[18]]), then collapses after [[12]] hours. Can be cut with any magical weapon or edged weapon wielded with +[[2]] mods.}}{{materials=a snake skin and a piece of sinew from a strong animal, costing 5sp to source, to weave into the cordlike object from which he will make the snare. Only the caster\'s holy symbol is otherwise needed}}'},
+ {name:'Speak-With-Animals',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpeak With Animals\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Animal,Divination}}Specs=[Speak-with-Animals,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[30 ft](!rounds --aoe @{selected|token_id}|circle|feet|0|60||magic|true)}}{{duration=[[[2*@{selected|Casting-Level}]] rounds](!rounds --target caster|@{selected|token_id}|Speak-With-Animals|[[2*@{selected|casting-level}]]|-1|Able to speak with the animals, no guarantee they\'ll deign to talk to you!|snail)}}{{aoe=[[1]] normal or giant animal that is not mindless}}{{save=None}}{{reference=PHB p207}}SpellData=[w:,lv:2,sp:5,gp:0,cs:VS,sph:Animal|Divination]{{effects=Communicate with any warm- or cold-blooded normal or giant animal that is not mindless. Terse \\amp evasive likely, stupid ones make inane comments. If same alignment, might do a favour. Differs from *Speak with Monsters* for this spell allows conversation only with non-fantastic creatures.}}'},
+ {name:'Speak-With-Dead',type:'PRspellL3',ct:'100',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpeak With Dead\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Necromancy}}{{sphere=Divination}}Specs=[Speak-with-Dead,PRspellL3,1H,Necromancy]{{components=V,S,M}}{{time=[[1]]turn}}{{range=[[1]]yd}}{{duration=Special}}{{aoe=[[1]] creature}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 Saving Throw)}}{{reference=PHB p214}}SpellData=[w:Speak-With-Dead,lv:3,sp:100,gp:10,cs:VSM,sph:Divination]{{effects=Ask several questions of a dead creature in a set period of time and receive answers according to the knowledge of that creature.}}{{materials=The priest needs a holy symbol and 10gp of burning incense in order to cast this spell upon the body, remains, or a portion thereof. The remains are not expended.}}'},
+ {name:'Speak-With-Plants',type:'PRspellL4',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpeak With Plants\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Speak-with-Plants,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[1]]turn}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]]rounds}}{{aoe=[30ft. radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||magic|true)}}{{save=None}}{{reference=PHB p220}}SpellData=[w:Speak-with-Plants,lv:4,sp:100,gp:0,cs:VSM,sph:Plant]{{effects=Converse, in very rudimentary terms, with all sorts of living vegetables (including fungi, molds, and plantlike monsters, such as shambling mounds) and to exercise limited control over normal plants (i.e., not monsters or plantlike creatures).}}{{materials=A drop of water, a pinch of dung, and a flame (all free).}}'},
+ {name:'Speak-with-Monsters',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpeak with Monsters\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Divination}}Specs=[Speak With Monsters,PRspellL6,1H,Alteration]{{components=V,S}}{{range=[[[30]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{time=[[9]]}}{{duration=[[[2*@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Speak-with-monsters|[[2*@{selected|casting-level}]]|-1|Doing a Dolittle - speaking with monsters|overdrive)}}{{aoe=The caster}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Speak with Monsters,lv:6,sp:9,gp:0,cs:VS,sph:Divination]{{effects=Converse with any type of creature that has any form of communicative ability (including empathic, tactile, pheromonic, etc.).}}'},
+ {name:'Spectral-Senses',type:'PRspellL1',ct:'4',charge:'uncharged',cost:'5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpectral Senses\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 1 Priest}}{{school=Divination/Necromancy}}{{sphere=Divination,Nectomantic}}Specs=[Spectral-Senses,PRspellL1,1H,Divination|Necromancy]{{components=V,S,M}}{{time=[[4]]}}{{range=[[[30*@{selected|Casting-Level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[60*@{selected|Casting-Level}]]||magic|true)}}{{duration=[[[@{selected|Casting-Level}]] hours](!rounds --target caster|@{selected|token_id}|Spectral-Senses|[[60*@{selected|casting-level}]]|-1|Borrowing the senses of a skeleton or zombie|skull)}}{{aoe=Caster}}{{save=None}}{{reference=The Complete Book of Necromancers, by Steve Kurtz}}SpellData=[w:Spectral-Senses,lv:1,sp:4,gp:5,cs:VSM,sph:Divination|Necromantic]{{effects=Establishes sensual link between caster and a skeleton or zombie in range. Caster sees and hears as if they were exactly where the undead creature is. Can also issue simple commands - link is spiritual so language is irrelevant. Ends abruptly if caster or creature moves out of range or to another plane. Can alternatively cast on an inanimate corpse. See and hear as if there but can\'t command or animate.}}{{materials=Priests holy symbol and a black hooded cowl costing 100gp which can be used 20 times, worn over eyes \\amp ears to aid concentration.}}'},
+ {name:'Spell-Immunity',type:'PRspellL4',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpell Immunity\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Abjuration}}{{sphere=Protection}}Specs=[Spell-Immunity,PRspellL4,1H,Abjuration]{{components=V,S,M}}{{time=[[1]] round}}{{range=Touch}}{{duration=[[[@{selected|Casting-Level}]] turns](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who is immune?|token_id}|Spell-Immunity|[[10*@{selected|casting-level}]]|-1|Immune from \\amp#63;{Immunity from which spell?}|Interdiction)}}{{aoe=[[1]] creature}}{{save=None}}{{reference=PHB p220}}SpellData=[w:Spell-Immunity,lv:4,sp:10,gp:0,cs:VSM,sph:Protection]{{effects=Renders a creature touched immune to the effects of a specified spell of 4th level or lower.}}{{materials=the same as that for the spell to be protected against.}}'},
+ {name:'Spike-Growth',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpike Growth\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration,Enchantment}}{{sphere=Plant}}Specs=[Spike-Growth,PRspellL3,1H,Alteration|Enchantment]{{components=V,S,M}}{{time=[[6]]}}{{range=[[60]]yds }}!setattr --silent --charid @{selected|character_id} --spell-duration|{{duration=[[10*(@{selected|casting-level}+([[3d4]]))]]rounds}}!!!{{aoe=[[[10*@{selected|casting-level}]]sq.ft.](!rounds --aoe @{selected|token_id}||feet|180|||acid)}}{{save=None}}{{reference=PHB p214}}{{damage=[Make spikey](!rounds --target caster|@{selected|token_id}|Spike-Growth|\\amp#64;{selected|spell-duration}|-1|The designated area is very spikey|tread)}}SpellData=[w:Spike-Growth,lv:3,sp:6,gp:0,cs:VSM,sph:Plant]{{effects=Wherever any type of plant growth of moderate size or density is found, this spell can be used to make the ground-covering vegetation or roots and rootlets in the area become very hard and sharply pointed, like caltrops, meaning that for each 10 feet of movement through the area, the victim suffers 2d4 points of damage and save vs spell or their movement rate is reduced by 1/3 of its current total.}}{{materials=The priest\'s holy symbol and either seven sharp thorns or seven small twigs, costing nothing, each sharpened to a point.}}'},
+ {name:'Spike-Stones',type:'PRspellL5',ct:'6',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpike Stones\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration, Enchantment}}{{sphere=Elemental (Earth)}}Specs=[Spike Stones,PRspellL5,1H,Alteration|Enchantment]{{components=V,S,M}}{{time=[[6]]}}{{range=[[30]] yards}}!setattr --silent --charid @{selected|character_id} --spell-duration|{{duration=[[3d4+@{selected|casting-level}]] turns}}!!!{{aoe=[@{selected|casting-level} x 10sq.ft.](!rounds --aoe @{selected|token_id}|rectangle|feet|90|||acid), 1 spike per sq.ft.}}{{save=None}}{{damage=[Make spikes](!rounds --target caster|@{selected|token_id}|Spike-Stones|\\amp#91;[\\amp#64;{selected|spell-duration}*10]\\amp#93;|-1|The stone spikes are still sharp|edge-crack)}}{{reference=PHB p225}}SpellData=[w:Spike Stones,lv:5,sp:6,gp:0.5,cs:VSM,sph:Elemental-Earth]{{effects=Causes rock to shape itself into long, sharp points that tend to blend into the background, which impede progress through an area and to inflict damage.}}{{materials=Four tiny stalactites, which cost 5sp to collect}}'},
+ {name:'Spiritual-Hammer',type:'Innate-Melee|PRspellL2|Innate-Melee|Innate-Melee',ct:'3',charge:'uncharged',cost:'2',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSpiritual Hammer\nas a level @{selected|Casting-Level} caster}}Specs=[Spiritual-Hammer,Innate-Melee|PRspellL2,1H,Evocation],[Spiritual-Hammer,Innate-Melee,1H,Clubs],[Spiritual-Hammer,Innate-Melee,1H,Clubs]{{splevel=Level 2 Priest}}ToHitData=[w:Spiritual Hammer+1,prlv:1:6,+:1,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:3],[w:Spiritual Hammer+2,prlv:7:12,+:2,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:2],[w:Spiritual Hammer+3,prlv:13,+:3,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:1]{{school=Invocation}}{{sphere=Combat}}DmgData=[w:Spiritual Hammer+1,sb:0,+:1,sm:1+1d4,l:1d4],[w:Spiritual Hammer+2,sb:0,+:2,sm:1+1d4,l:1d4],[w:Spiritual Hammer+3,sb:0,+:3,sm:1+1d4,l:1d4]{{components=V,S,M}}weapData=[on:\\api;rounds --target caster|@{selected|token_id}|Spiritual-Hammer|\\lbrak;\\lbrak;3+@{selected|Casting-Level}\\rbrak;\\rbrak;|-1|Magical weapon in direction facing requires concentration|archery-target,off:\\api;!rounds --removetargetstatus @{selected|token_id}|Spiritual-Hmmer]{{time=[[5]]}}{{range=[[10*@{selected|Casting-Level}]] yards}}{{duration=[[3+@{selected|Casting-Level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p207}}{{damage=SM [1d4+1](!\\amp#13;\\amp#47;r 1d4+1) or L [1d4](!\\amp#13;\\amp#47;r 1d4) +[[{{(ceil(@{selected|Casting-Level}/6)),3}kl1}]]}}{{damagetype=Bludgeoning}}SpellData=[w:Spiritual-Hammer,lv:2,sp:5,gp:2,cs:VSM,sph:Combat]{{effects=Base Thac0 same as caster [[@{selected|thac0-base}]] without strength bonus plus magical plus of +[[{{(ceil(@{selected|Casting-Level}/6)),3}kl1}]]. Damage is plus magical bonus but no others.}}{{materials=A normal war hammer (cost 2gp) hurled towards opponent, which disappears as spell is cast.}}{{use=Take the Spiritual Hammer in-hand using the *Change Weapon* menu for the duration of the spell, and use it to attack opponents. It will disappear when the duration expires or you *Change Weapon* to another weapon.}}'},
+ {name:'Starshine',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nStarshine\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Evocation,Illusion/Phantasm}}{{sphere=Sun}}Specs=[Starshine,PRspellL3,1H,Evocation|Illusion-Phantasm]{{components=V,S,M}}{{time=[[6]]}}{{range=[[10*@{selected|casting-level}]]yds }}{{duration=[[[@{selected|casting-level}]]turns](!rounds --target caster|@{selected|token_id}|Starshine|[[10*@{selected|casting-level}]]|-1|Starshine gives sight as per bright moonlit night|frozen-orb)}}{{aoe=[[[10*@{selected|casting-level}]]sq.ft.](!rounds --aoe @{selected|token_id}||feet|[[30*@{selected|casting-level}]]|||light)}}{{save=None}}{{reference=PHB p214}}SpellData=[w:Starshine,lv:3,sp:6,gp:0.5,cs:VSM,sph:Sun]{{effects=Softly illuminate an area as if it were exposed to a clear night sky filled with stars.}}{{materials=Several stalks from an amaryllis plant (especially Hypoxis) costing 5sp, and several holly berries.}}'},
+ {name:'Sticks-to-Snakes',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSticks to Snakes\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Sticks-to-Snakes,PRspellL4,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[30]]yds}}{{duration=[[[2*@{selected|casting-level}]] rounds](!rounds --target caster|@{selected|token_id}|Sticks-to-Snakes|[[2*@{selected|casting-level}]]|-1|Sticks have become snakes \\amp attack as you comand!|all-for-one)}}{{aoe=[1d4](!\\amp#13;\\amp#47;r 1d4) + [[@{selected|casting-level}]] sticks in a [10ft. cube](!rounds --aoe @{selected|token_id}|square|feet|90|10||magic)}}{{save=None}}{{reference=PHB p220}}SpellData=[w:Sticks-to-Snakes,lv:4,sp:7,gp:0.5,cs:VSM,sph:Plant]{{effects=Change 1d4 sticks, plus one stick per experience level, into snakes which attack as commanded by the priest. Typical snakes have 2HD, AC 6, move of 9, and either constricts for 1d4+1HP per round or bites for 1HP plus poison (if any - venomous chance is 5% per caster level, if the spellcaster desires).}}{{materials=A small piece of bark and several snake scales, costing 5sp.}}'},
+ {name:'Stone-Shape',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nStone Shape\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Earth)}}Specs=[Stone-Shape,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=[[9+@{selected|casting-level}]]sq.ft.}}{{save=None}}{{reference=PHB p214}}SpellData=[w:Stone-Shape,lv:3,sp:10,gp:0.01,cs:VSM,sph:Elemental-Earth]{{effects=Form an existing piece of stone into any shape that suits the caster\'s purposes.}}{{materials=Soft clay that must be worked into roughly the desired shape of the stone object, and then touched to the stone when the spell is uttered. 1cp of materials \\amp effort}}'},
+ {name:'Stone-Tell',type:'PRspellL6',ct:'100',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nStone Tell\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Divination}}{{sphere=Elemental (Earth), Divination}}Specs=[Stone Tell,PRspellL6,1H,Divination]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] turn}}{{duration=[[[1]] turn](!rounds --target caster|@{selected|token_id}|Stone-tell|10|-1|Communing with a rock...|broken-skull)}}{{aoe=[1 cubic yard](!rounds --aoe @{selected|token_id}|square|yards|0|1|1|magic|true)}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Stone Tell,lv:6,sp:100,gp:1,cs:VSM,sph:Elemental-Earth|Divination]{{effects=The very stones speak and relate to the caster who or what has touched them as well as revealing what is covered, concealed, or simply behind them.}}{{materials=A drop of mercury, a rare \'magical\' liquid metal costing 1gp a drop, and a bit of clay}}'},
+ {name:'Straighten-Wood',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nStraighten Wood\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest (reversable)}}{{school=Alteration}}{{sphere=Plant}}Specs=[Straighten Wood,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[[10*@{selected|Casting-Level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[20*@{selected|Casting-Level}]]||lightning)}}{{duration=Permanent}}{{aoe=[[15]]x[[1]]inch dia. x [[@{selected|Casting-Level}]] of wood}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. spell (Straighten Wood)}}{{reference=PHB p208 (reverse of *Warp Wood*)}}SpellData=[w:Straighten Wood,lv:2,sp:5,gp:0,cs:VS,sph:Plant]{{effects=Straightens bent or crooked wood, or reverses the effects of a *warp wood* spell.}}'},
+ {name:'Summon-Insects',type:'PRspellL3',ct:'10',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSummon Insects\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Conjuration/Summoning}}{{sphere=Animal}}Specs=[Summon-Insects,PRspellL3,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[1]] round}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||acid|true)}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=[[1]] creature}}{{save=None}}{{reference=PHB p214}}{{damage=[[2]]HP/rd if flee or defend, [[4]]HP otherwise}}{{damagetype=\nBites or Stings}}SpellData=[w:Summon-Insects,lv:3,sp:10,gp:0.01,cs:VSM,sph:Animal]{{effects=Roll [1d100](!\\amp#13;\\amp#47;r 1d100) - 70% summons bees or biting flies or hornets or wasps. 30% summons biting ants or pinching beetles. 2pts per round if just flee \\amp fend off, 4pts otherwise and [[0-2]] on attack \\amp +[[2]] on AC. Can then go after 2nd target after 1 round.}}{{materials=The caster\'s holy symbol, a flower petal, and a bit of mud or wet clay. Total cost 1cp}}'},
+ {name:'Tongues',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTongues\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest}}{{school=Alteration}}{{sphere=Divination}}Specs=[Tongues,PRspellL4,1H,Alteration]{{components=V,S}}{{time=[[7]]}}{{range=[[0]]}}{{duration=[[1]] turn}}{{aoe=The caster}}{{save=None}}{{reference=PHB p220}}{{healing=[Universal Translator](!rounds --target caster|@{selected|token_id}|PR-Tongues-Translate|10|-1|Speaks your language|flying-flag)}}SpellData=[w:Tongues,lv:4,sp:7,gp:0,cs:VS,sph:Divination]{{effects=Speak and understand additional specified languages, whether they are racial tongues or regional dialects, but not communications of animals or mindless creatures.}}'},
+ {name:'Transmute-Dust-to-Water',type:'PRspellL6',ct:'8',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransmute Dust to Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration (Reversable)}}{{sphere=Elemental (Water, Earth)}}Specs=[Transmute Water to Dust,PRspellL6,1H,Alteration]{{components=V,S,M}}{{range=[[60]] yards}}{{time=[[8]]}}{{duration=Permanent}}{{aoe=[@{selected|casting-level} cubic yards](!rounds --aoe @{selected|token_id}|rectangle|yards|60|||magic)}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Transmute Water to Dust,lv:6,sp:8,gp:500,cs:VSM,sph:Elemental-Water|Elemental-Earth]{{effects=Simply a very high-powered create water spell.}}{{materials=Diamond dust of at least 500 gp value, a bit of sea shell, and the caster\'s holy symbol}}'},
+ {name:'Transmute-Mud-to-Rock',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'00.2',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransmute Mud to Rock\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration (Reversable)}}{{sphere=Elemental (Earth, Water)}}Specs=[Transmute Mud to Rock,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=[[160]] yards}}{{duration=Special}}{{aoe=[@{selected|casting-level} x 20ft.cube](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||magic)}}{{save=None}}{{reference=PHB p225}}SpellData=[w:Transmute Mud to Rock,lv:5,sp:8,gp:00.2,cs:VSM,sph:Elemental-Earth-Water]{{effects=Hardens normal mud or quicksand into soft stone (sandstone or similar mineral) permanently unless magically changed. Creatures in the mud are allowed a saving throw to escape before the area is hardened to stone. Dry sand is unaffected}}{{materials=Sand, lime (costing 2cp), and water}}'},
+ {name:'Transmute-Rock-to-Mud',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransmute Rock to Mud\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Alteration (Reversable)}}{{sphere=Elemental (Earth, Water)}}Specs=[Transmute Rock to Mud,PRspellL5,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=[[160]] yards}}{{duration=Special}}{{aoe=[@{selected|casting-level} x 20ft.cube](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||magic)}}{{save=None}}{{reference=PHB p225}}SpellData=[w:Transmute Rock to Mud,lv:5,sp:8,gp:0,cs:VSM,sph:Elemental-Earth-Water]{{effects=Turns natural rock of any sort into an equal volume of mud.}}{{materials=Clay and water (free)}}'},
+ {name:'Transmute-Water-to-Dust',type:'PRspellL6',ct:'8',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransmute Water to Dust\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration (Reversable)}}{{sphere=Elemental (Water, Earth)}}Specs=[Transmute Water to Dust,PRspellL6,1H,Alteration]{{components=V,S,M}}{{range=[[60]] yards}}{{time=[[8]]}}{{duration=Permanent}}{{aoe=[@{selected|casting-level} cubic yards](!rounds --aoe @{selected|token_id}|rectangle|yards|60|||magic)}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Transmute Water to Dust spell)}}{{reference=PHB p229}}SpellData=[w:Transmute Water to Dust,lv:6,sp:8,gp:500,cs:VSM,sph:Elemental-Water|Elemental-Earth]{{effects=The subject area instantly undergoes a change from liquid to powdery dust.}}{{materials=Diamond dust of at least 500 gp value, a bit of sea shell, and the caster\'s holy symbol}}'},
+ {name:'Transport-via-Plants',type:'PRspellL6',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransport via Plants\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Transport via Plants,PRspellL6,1H,Alteration]{{components=V,S}}{{range=Touch}}{{time=[[4]]}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Transport via Plants,lv:6,sp:4,gp:0,cs:VS,sph:Plant]{{effects=Enter any plant (human-sized or larger) and pass any distance to a plant of the same species in a single round, regardless of the distance separating the two. }}'},
+ {name:'Tree',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTree\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Tree,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[6]]}}{{range=[[0]]}}{{duration=[[6+@{selected|Casting-Level}]] turns}}{{aoe=The caster}}{{save=None}}{{reference=PHB p215}}{{healing=[Make like a tree...](!rounds --target caster|@{selected|token_id}|Tree|[[10*(6+@{selected|Casting-Level})]]|-1|Make like a tree... dude! Normal AC \\amp HP, instant revert|three-leaves)}}SpellData=[w:Tree,lv:3,sp:6,gp:0,cs:VSM,sph:Plant]{{effects=Caster assumes form of small living tree, or large dead tree.}}{{materials=The priest\'s holy symbol and a twig from a tree (no cost).}}'},
+ {name:'Trip',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTrip\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Enchantment/Charm}}{{sphere=Plant}}Specs=[Trip,PRspellL2,1H,Enchantment]{{components=V,S}}{{time=[[5]]}}{{range=Touch}}{{duration=[[@{selected|Casting-Level}]]turns}}{{aoe=[[1]]object up to [[10]]ft long}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. spell (Trip)}}{{reference=PHB p207}}{{damage=[[1]]HP and [1d4+1](!\\amp#13;\\amp#47;r 1d4+1 rounds stunned)rounds stunned if on hard surface}}SpellData=[w:Trip,lv:2,sp:5,gp:0,cs:VS,sph:Plant]{{effects=Causes an object to rise slightly off the ground or floor it is resting on to trip most creatures crossing it, if they fail to save vs. spell.}}'},
+ {name:'True-Seeing',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'300',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTrue Seeing\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Divination (Reversable)}}{{sphere=Divination}}Specs=[True Seeing,PRspellL5,1H,Divination]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch}}{{duration=[[@{selected|casting-level}]] rounds}}{{aoe=[1 creature](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who will see truly?|token_id}|True-Seeing|@{selected|casting-level}|-1|Can see truly now|bleeding-eye)}}{{save=None}}{{reference=PHB p225}}SpellData=[w:True Seeing,lv:5,sp:8,gp:300,cs:VSM,sph:Divination]{{effects=Confers upon the recipient the ability to see all things as they actually are.}}{{materials=An ointment for the eyes that is made from very rare mushroom powder, saffron, and fat and costs no less than 300 gp per use \\amp 1d6 months to create}}'},
+ {name:'Turn-Wood',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTurn Wood\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Plant}}Specs=[Turn Wood,PRspellL6,1H,Alteration]{{components=V,S}}{{range=[[0]]}}{{time=[[9]]}}{{duration=[@{selected|casting-level} rounds](!rounds --target caster|@{selected|token_id}|Turn-Wood|@{selected|casting-level}|-1|The wood is pushed away|strong)}}{{aoe=[[[20*@{selected|casting-level}]]ft x 120ft](!rounds --aoe @{selected|token_id}|bolt|feet|0|[[20*@{selected|casting-level}]]|120|magic|)}}{{save=None}}{{reference=PHB p229}}SpellData=[w:Turn Wood,lv:6,sp:9,gp:0,cs:VS,sph:Plant]{{effects=Waves of force roll forth from the caster, moving in the direction he faces and causing all wooden objects in the path of the spell to be pushed away from the caster to the limit of the area of effect.}}'},
+ {name:'Undetectable-Alignment',type:'PRspellL2',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nUndetectable Alignment\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Divination}}{{sphere=Divination}}Specs=[Undetectable Alignment,PRspellL2,1H,Divination]{{components=V,S}}{{time=[[1]] round}}{{range=[10 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20||magic|true)}}{{duration=[[[24]] hours](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s alignment do you want to hide?|token_id}|Undetectable-Alignment|1440|-1|Noone can detect your alignment|white-tower)}}{{aoe=[[1]] creature or object}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p206}}SpellData=[w:Undetectable Alignment,lv:2,sp:10,gp:0,cs:VS,sph:Divination]{{effects=Conceals the alignment of an object or creature for [[24]] hours}}'},
+ {name:'Undetectable-Lie',type:'PRspellL4',ct:'7',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nUndetectable Lie\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 4 Priest (reversable)}}{{school=Divination}}{{sphere=Divination}}Specs=[Undetectable-Lie,PRspellL4,1H,Divination]{{components=V,S,M}}{{time=[[7]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=[[1]] creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs spell for detect lie)}}{{reference=PHB p217}}{{healing=[Make very believable](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who wants to be believable?|token_id}|Undetectable-Lie|1440|-1|Lies very convincingly|aura)}}SpellData=[w:Undetectable Lie,lv:4,sp:7,gp:0.1,cs:VSM,sph:Divination]{{effects=Prevents the magical detection of lies spoken by the creature for 24 hours. However, does not prevent normal determination of a lie by other means}}{{materials=1sp worth of brass dust}}'},
+ {name:'Unholy-Word',type:'PRspellL7',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nUnholy Word\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration-Summoning (Reversable)}}{{sphere=Combat}}Specs=[Unholy Word,PRspellL7,0H,Conjuration-Summoning]{{components=V}}{{range=[[0]]}}{{time=[[1]]}}{{duration=Special}}{{aoe=[30ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||light|true)}}{{save=None}}{{reference=PHB p234}}SpellData=[w:Unholy Word,lv:7,sp:1,gp:0,cs:V,sph:Combat]{{effects=Creates magic of tremendous power. It drives off good creatures from other planes, forcing them to return to their own planes of existence, provided the speaker is in his home plane.}}'},
+ {name:'Wall-of-Fire',type:'PRspellL5',ct:'8',charge:'uncharged',cost:'0.05',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWall of Fire\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 5 Priest}}{{school=Conjuration-Summoning}}{{sphere=Elemental (Fire)}}Specs=[Wall of Fire,PRspellL5,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[8]]}}{{range=[[80]] yards}}{{duration=[While concentrating](!rounds --target caster|@{selected|token_id}|Wall-of-Fire-PR|99|0|Concentrating on maintaining the Wall of Fire|radioactive)}}{{aoe=[Sheet of Flame](!rounds --aoe @{selected|token_id}|wall|feet|240||3|fire) or [A Ring](!rounds --aoe @{selected|token_id}|circle|feet|240|||fire)}}{{save=None}}{{damage=[passing through 4d4+@{selected|casting-level}](!\\amp#13;\\amp#47;gmroll 4d4+@{selected|casting-level} fire damage) [within 10ft 2d4](!\\amp#13;\\amp#47;gmroll 2d4 fire damage) [within 20ft 1d4](!\\amp#13;\\amp#47;gmroll 1d4 fire damage)}}{{reference=PHB p225}}SpellData=[w:Wall of Fire,lv:5,sp:8,gp:0.05,cs:VSM,sph:Elemental-Fire]{{effects=Brings forth an immobile, blazing curtain of magical fire of shimmering color--yellow-green or amber (different from the 4th-level wizard version).}}{{materials=Phosphorus worth 5cp}}'},
+ {name:'Wall-of-Thorns',type:'PRspellL6',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWall of Thorns\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning}}{{sphere=Plant, Creation}}Specs=[Wall of Thorns,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[80]] yards}}{{time=[[9]]}}{{duration=[@{selected|casting-level} turns](!rounds --target caster|@{selected|token_id}|Wall-of-Thorns|[[10@{selected|casting-level}]]|-1|A wall of spikey growth exists|interdiction)}}{{aoe=[[[@{selected|casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|wall|feet|240|||acid)}}{{save=None}}{{reference=PHB p230}}SpellData=[w:Wall of Thorns,lv:6,sp:9,gp:0,cs:VS,sph:Plant|Creation]{{effects=Creates a barrier of very tough, pliable, tangled brush bearing needle-sharp thorns as long as a person\'s finger. Any creature breaking through (or crashing into) the wall of thorns suffers 8 points of damage, plus an additional amount of damage equal to the creature\'s AC.}}'},
+ {name:'Warp-Wood',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWarp Wood\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest (reversable)}}{{school=Alteration}}{{sphere=Plant}}Specs=[Warp-Wood,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[[10*@{selected|Casting-Level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[20*@{selected|Casting-Level}]]||lightning)}}{{duration=Permanent}}{{aoe=[[15]]x[[1]]inch dia. x [[@{selected|Casting-Level}]] of wood}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs. spell (Warp Wood)}}{{reference=PHB p208}}SpellData=[w:Warp-Wood,lv:2,sp:5,gp:0,cs:VS,sph:Plant]{{effects=Causes a volume of wood to bend and warp, permanently destroying its straightness, form, and strength.}}'},
+ {name:'Water-Breathing',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWater Breathing\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Water-Breathing,PRspellL3,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=Touch}}{{duration=[[?{How many water breathers?|1}]] creatures for [[floor(@{selected|casting-level}/?{How many water breathers?|1})]]hours [[floor((60*@{selected|casting-level}/?{How many water breathers?|1})%60)]] minutes}}{{aoe=Special}}{{save=None}}{{reference=PHB p215}}{{healing=[Grant gills](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Give aqualung to who?|token_id}|Water-Breathing|[[60*@{selected|casting-level}/([[?{How many water breathers?|1}]])]]|-1|Breath water like a fish|ninja-mask)}}SpellData=[w:Water-Breathing,lv:3,sp:6,gp:0,cs:VS,sph:Elemental-Water]{{effects=The recipient is able to breathe under water freely for the duration of the spell--i.e., one hour for each experience level of the caster. The priest can divide the base duration between multiple characters.\nNote that the spell does not prevent the recipient creature from breathing in its natural element.}}'},
+ {name:'Water-Summoning',type:'PRspellL6',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWater Summoning\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Conjuration-Summoning}}{{sphere=Weather}}Specs=[Water Summoning,PRspellL6,1H,Conjuration-Summoning]{{components=V,S}}{{range=[[0]]}}{{time=[[1]] turn}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p230}}SpellData=[w:Water Summoning,lv:6,sp:100,gp:0,cs:VS,sph:Weather]{{effects=Calls forth weather appropriate to the climate and season of the area he is in, which is not under the control of the caster.}}'},
+ {name:'Water-Walk',type:'PRspellL3',ct:'6',charge:'uncharged',cost:'0.01',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWater Walk\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Water-Walk,PRspellL3,1H,Alteration]{{components=V,S,M}}{{time=[[6]]}}{{range=Touch}}{{duration=[[1+@{selected|casting-level}]]Turns}}{{aoe=[[@{selected|casting-level}-4]] creatures}}{{save=None}}{{reference=PHB p215}}{{healing=[Splash don\'t drown](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Give wellies to who?|token_id}|Water-Breathing|[[10+(10*@{selected|casting-level})]]|-1|Walk on water|tread)}}SpellData=[w:Water-Walk,lv:3,sp:6,gp:0.01,cs:VSM,sph:Elemental-Water]{{effects=Empower one or more creatures to tread upon any liquid as if it were firm ground; this includes mud, quicksand, oil, running water, and snow.}}{{materials=A piece of cork costing 1cp and the priest\'s holy symbol.}}'},
+ {name:'Withdraw',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWithdraw\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Alteration}}{{sphere=Protection}}Specs=[Withdraw,PRspellL2,1H,Alteration]{{components=V,S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=Special}}{{aoe=The caster}}{{save=None}}{{reference=PHB p208}}SpellData=[w:Withdraw,lv:2,sp:5,gp:0,cs:VS,sph:Protection]{{effects=In effect alters the flow of time with regard to the caster. While but one round of time passes for those not affected by the spell, the priest is able to spend two rounds, plus one round per level = [[2+@{selected|Casting-Level}]], in contemplation.}}'},
+ {name:'Word-of-Recall',type:'PRspellL6',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWord of Recall\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 6 Priest}}{{school=Alteration}}{{sphere=Summoning}}Specs=[Word of Recall,PRspellL6,0H,Alteration]{{components=V}}{{range=[[0]]}}{{time=[[1]]}}{{duration=Special}}{{aoe=The caster}}{{save=None}}{{reference=PHB p230}}SpellData=[w:Word of Recall,lv:6,sp:1,gp:0,cs:V,sph:Summoning]{{effects=Takes the priest instantly back to his sanctuary when the word is uttered.}}'},
+ {name:'Wyvern-Watch',type:'PRspellL2',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWyvern Watch\nas a level @{selected|Casting-Level} caster}}{{splevel=Level 2 Priest}}{{school=Evocation}}{{sphere=Guardian}}Specs=[Wyvern-Watch,PRspellL2,1H,Evocation]{{components=V,S,M}}{{time=[[5]]}}{{range=[[30]] yards}}{{duration=[[8]] hours or until strike}}{{aoe=[10ft radius sphere](!rounds --aoe @{selected|token_id}|circle|feet|90|20||magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{reference=PHB p208}}SpellData=[w:Wyvern-Watch,lv:2,sp:5,gp:0,cs:VSM,sph:Guardian]{{effects=Creates an insubstantial haze. Used to guard an area. Any creature approaching within [[10]]ft of area must make a save vs spell or be paralysed for [[@{selected|Casting-Level}]] rounds.}}{{materials=Requires the Priest\'s holy symbol.}}'},
+ ]},
+ Powers_DB: {bio:'Powers Database
v6.26 21/05/2023
This database holds the definitions and API calls to enact Character, NPC & Monster Powers. Powers can be memorised and, unlike spells, can be specified for use more than once a day or even at will. If all daily uses are used, they can be refreshed on a long rest (short rests have no effect). Characters, NPCs and Monsters can learn, memorise and use these spells via the abilities, menus and commands of the MagicMaster API
Important Note: most of the spell macros require a Roll20 Pro membership, and the installation of the ChatSetAttr, TokenMod, MagicMaster and RoundMaster API Scripts, to allow parameter passing between macros, update of character sheet variables, and marking spell effects on tokens. If you do not have this level of subscription, I highly recommend you get it as a DM, as you get lots of other goodies as well. If you want to know how to load the API Scripts to your game, the RoLL20 API help here gives guidance, or Richard can help you.
Instructions
In order to understand the format of spell macros in this database and how to change or add to them, please refer to the MagicMaster API documentation.',
+ gmnotes:'Change Log:
v6.26 21/05/2023 One new power associated with the Helm of Teleportation
v6.25 30/04/2023 Added powers to support added miscellaneous items
v6.24 31/01/2023 Added powers to support new magic items
v6.17-22 16/12/2022 Additional powers to support Creatures database
v6.16 25/11/2022 Added powers to support the Creatures database
v6.15 14/11/2022 Added Race powers in support of the Race Database.
v6.11 12/10/2022 Added Detect Illusions
v6.10 25/09/2022 Moved to RPGM Library and updated templates
v6.03 14/07/2022 Removed hard-coded whisper commands on database entries as now directed to correct player(s) programmatically
v6.02 23/06/2022 Added powers for Shaman
v6.01 11/05/2022 Added powers for the Priest-of-the-Sea standard Priest class
v5.9 06/04/2022 Adapted to use --display-ability command for chaining abilities
v5.8 23/02/2022 Added a number of Powers from *The Complete Priest\'s Handbook
v5.7 04/02/2022 Added "End Effect" buttons to "Rage" power
v5.6 01/01/2022 Updated to common release version
v5.4 - 5.5 Skipped to even up version numbers
v5.3 07/12/2021 Added turning dice roll to *Turn Undead* power
v5.2 29/11/2021 Swapped PR-Light to Light-PR for more intuitive listing, and did same for similar powers
v5.1 31/10/2021 Added Powers for monsters from "The Undiscovered Caverns"
v5.0 31/10/2021 Encoded using machine readable data to support API databases
v4.6.5 04/09/2021 Added powers for WPM Undiscovered Caverns
v4.6.4 15/07/2021 Expanded Manticore Tail Spikes to not need character sheet macros
v4.6.3 11/06/2021 Added powers for Ghosts of Saltmarsh
v4.6.2 01/05/2021 Extensive bug checking & fixing
v4.6.1 14/04/2021 Added Spiritual Hammer and Prayer as powers for a Priest of War
v4.6 28/03/2021 Edited all macros to use the MagicMaster API for targeting and charges
v4.5.3 26/03/2021 Added regeneration every turn capability to Regenerate power (in addition to ability for each use of the power).
v4.5.2 14/03/2021 Changed cost for using Command power to 0GP
v4.5.1 09/03/2021 Added the missing \'ct--\' required for removing Powers to set the speed & cost for a \'-\'
v4.5 27/02/2021 Changed calls to @{Powers|Use-Another-Charge} to use the MagicMaster API call instead
v4.4.4 14/02/2021 Changed all !setattr --sel parameters to be --charid instead, so they can work more easily with the MagicMaster API.
v4.4.3 04/02/2021 Added fear power for mummies, and corrected some targeting bugs
v4.4.2 19/01/2021 Added Priest of Life class spells as powers.
v4.4.1 17/12/2020 Added in missing Spectral Hand power
v4.4 22/11/2020 Separated out mu-casting-level and pr-casting-level (casting-level also retained for backwards compatibility). This is needed as casters with dual MU/PR class may cast some powers at different levels.
v4.3 17/11/2020 Split off the mechanics of the Powers execution into the Powers library. leaving the Power description macros here.
v4.2 09/11/2020 Added special menus for adding and managing Magic Item powers
v4.1 01/11/2020 Added NWP Healing as a power: requires the new feature of multiple use decrementing the power uses.
v4.0 29/10/2020 Same as v3.4.1 just aligning version numbers with v4 macro library release
v3.4.1 29/10/2020 Fixed bug with initialising sheet variables
v3.4 20/10/2020 Updated to support Lost & Found campaign
v3.3.1 12/10/2020 Updated Long Rests to set ammo maximums to ammo remaining, to reflect that any not recovered when you rest are lost
v3.3 06/10/2020 Added thieving abilities as powers (mainly to add markers), linked Long Rests to the DMs "End of Day" routine, and added a rest selection for non-spell users that restores Powers & recharging MIs
v3.2 22/09/2020 Updated to use new lag detection and selection control mechanisms
v3.1 03/09/2020 Added all powers for Arc and Hubert
v3.0 01/09/2020 Initial Release
v1-v2 Skipped these versions to bring in line with release numbers for other macro libraries
v0.1 26/08/2020 Initial Creation',
+ root:'Powers-DB',
+ api:'magic',
+ type:'spells',
+ controlledby:'all',
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/3077760/Vg6r8vmy8ANNrCZHGtul2w/thumb.png?1392175066',
+ version:6.26,
+ db:[{name:'-',type:'',ct:'0',charge:'uncharged',cost:'0',body:'@{selected|token_name} suddenly realises he is powerless! Choose another power instead.'},
+ {name:'AE-Aerial-Combat',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Air Elemental Aerial Combat}}Specs=[AE Aerial Combat,Power,0H,Innate Ability]{{Speed=[[0]]}}{{save=None}}{{Flying=[Start](!rounds --target caster|@{selected|token_id}|AE-Aerial-Combat|99|0|Gained +1 to hit and +4 damage bonus|fluffy-wing) or [Stop](!rounds --removetargetstatus @{selected|token_id}|AE-Aerial-Combat) Aerial Combat}}SpellData=[w:AE Aerial Combat,sp:0,cs:S,pd:-1]{{desc=Air elementals can be conjured in any area of open air where gusts of wind are present. The common air elemental appears as an amorphous, shifting cloud when it answers its summons to the Prime Material plane.}}{{desc1=**Combat:** While air elementals are not readily tangible to the inhabitants of planes other than its own, they can strike an opponent with a strong, focused blast of air that, like a giant, invisible fist, does 2-20 points of damage. The extremely rapid rate at which these creatures can move make them very useful on vast battlefields or in extended aerial combat. In fact, the air elemental\'s mastery of its natural element gives it a strong advantage in combat above the ground. In aerial battles, they gain a +1 to hit and a +4 to the damage they inflict.}}{{desc2=**Use:** Select the *Start Aerial Combat* button to change to aerial combat and get bonuses. When finished, *view* the Power again and use the *Stop Aerial Combat* button, or the DM can edit the status and remove it.}}'},
+ {name:'Analysis-Detection-Identification',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Analysis, Detection \\amp Identification}}Specs=[Analyse-Detect-Identify,Power,0H,Divination]{{Speed=[[10]]}}{{save=None}}{{Reference=*The Complete Priest\'s Handbook*, Designing Faiths}}SpellData=[w:Analyse-Detect-Identify,sp:10,pd:2]{{desc=Identify a category of persons, places, or things. The priest must be within 10\' of the object in order to identify it correctly; he does not have to see it, and the object can be hidden. In some cases, it could even be buried.\nIf the DM designs it as part of the ability, the priest can also analyze the object and get additional details about it. The type of information brought about by this analysis varies from object to object}}'},
+ {name:'Animate-Tree',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Animate Tree}}{{splevel=Power}}{{school=Alteration}}Specs=[Animate Tree,Power,1H,Alteration]{{components=V,M}}{{time=[[10]]}}{{range=Touch}}{{duration=6 rounds, plus 1 to animate \\amp 1 to take root}}{{aoe=One tree}}{{save=None}}SpellData=[w:Animate Tree,sp:10,cs:VM]{{effects=Cause a large [tree to move](!rounds --target caster|@{selected|token_id}|Animate Tree|8|-1|Tree starts to animate in round 1, can attack rounds 2 to 7 and roots in round 8|three-leaves) at a movement rate of 3 and attack as if it were a largest-sized treant, and in all other respects becoming a virtual treant for eight rounds per charge expended. Note that one round is required for the tree to animate, and it will return to rooting on the eighth, so only six of the initial eight rounds are effectively available for the attack function.}}{{Use=Press the [tree to move] button to set a status timer for the duration of the power}}'},
+ {name:'Aquatic-Shapechange',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nAquatic Shape Change\nas a Power}}{{splevel=Power}}{{school=Alteration}}Specs=[Aquatic Shapechange,Power,1H,Alteration]{{components=V,S}}{{time=[[9]]}}{{range=[[0]]}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Shapechange-Power|[[10*@{selected|casting-level}]]|-1|Masqurading as a different natural aquatic creature|aura)}}{{aoe=The caster}}{{save=None}}{{reference=PHB p37}}SpellData=[w:Aquatic Shapechange,sp:9,cs:VS]{{effects=A Priest of the Sea (or other priest) gains the ability to shapechange into an aquatic animal up to one or three times per day (DMs discression) after they reach 8th level. Each animal form can be used only once per day. The type of marine animal is at the DMs discression (an option is to leave to player\'s choice). Upon assuming a new form, the priest heals 10-60% (1d6 x 10%) of all damage he has suffered (round fractions down). The priest can only assume the form of a normal (real world) animal in its normal proportions, but by doing so he takes on all of that creature\'s characteristics -- its movement rate and abilities, its Armor Class, number of attacks, and damage per attack.\nThe priest\'s clothing and one item held in each hand also become part of the new body; these reappear when the priest resumes his normal shape. The items cannot be used while the priest is in animal form.}}'},
+ {name:'Astral-Travel-5',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} is using\nAstral Travel (five)\nas a power as a level @{selected|casting-level} caster}}{{splevel=Level 9 Wizard}}{{school=Evocation}}Specs=[Astral Travel 5,Power,1H,Evocation]{{components=V,M}}{{time=9}}{{range=Caster}}{{duration=Special}}{{aoe=Self}}{{save=None}}{{reference=DMG p153}}SpellData=[w:Astral Travel 5,sp:9,cs:VM]{{effects=Unlike the spell *Astral Spell*, transfers five creatures\' including the caster\'s, *material body* into the Astral Plane, meaning they can travel materially through the Astral Plane and emerge elsewhere on the Material Plane. Of course, as the creatures material body actually becomes Astral, no silver thread remains joining the two as the two are one.}}'},
+ {name:'Astral-Travel-self',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} is using\nAstral Travel (self)\nas a power as a level @{selected|casting-level} caster}}{{splevel=Level 9 Wizard}}{{school=Evocation}}Specs=[Astral Travel self,Power,1H,Evocation]{{components=V,M}}{{time=9}}{{range=Caster}}{{duration=Special}}{{aoe=Self}}{{save=None}}{{reference=DMG p153}}SpellData=[w:Astral Travel self,sp:9,cs:VM]{{effects=Unlike the spell *Astral Spell*, transfers the caster\'s *material body* into the Astral Plane, meaning they can travel materially through the Astral Plane and emerge elsewhere on the Material Plane. Of course, as the caster\'s material body actually becomes Astral, no silver thread remains joining the two as the two are one.}}'},
+ {name:'Beastmaster-Animal-Telepathy',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Beastmaster\nAnimal Telepathy}}{{splevel=Class Ability}}{{school=Enchantment-Charm}}Specs=[Beastmaster-Animal-Telepathy,Power,1H,Enchantment-Charm]{{components=None}}{{time=[[10]]}}{{range=[30 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|60||magic|true)}}{{duration=Special}}{{aoe=Special}}{{save=[Recruit](!\\amp#13;\\amp#47;gmroll 1d20 minus [[ceil(@{selected|casting-level}/3)]] save vs Rod) save vs Rod for animal to save vs being recruited}}SpellData=[w:Beastmaster Animal Telepathy,sp:10,cs:None]{{effects=The Beastmaster can establish telepathic communication with any normal or giant animal within 30\', if he does nothing else in the round. The animal must have a minimum Intelligence of 1. This has the following benefits:\n• The Beastmaster can communicate to the creature that he desires its friendship. If the offer is sincere (and the animal will be able to sense if it isn\'t), the creature can be calmed and will not attack or flee unless it is attacked.\n• The Beastmaster can recruit an animal he has befriended as a henchman if he is not at his limit and if the creature fails a saving throw vs. rods. The saving throw is penalized by -1 for every three levels of experience the Beastmaster has earned.\n*Animal Bonding:* The Beastmaster forms a mental bond with any animal he recruits as a henchman. There is no distance limit, but this ability does not cross planar boundaries. This bond has the following effects:\n•The Beastmaster can communicate directly with any animal henchman to which he has a bond.\n• He can see through the eyes of the animal by concentrating on the mental link. He can see through the eyes of only one creature in a round (himself included).\n• He has the animal lore proficiency with respect to the bonded animal. Furthermore, if he is mentally linked to the animal, success with the proficiency is automatic.}}'},
+ {name:'Beholder-Anti-Magic-Ray',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Anti-Magic Ray}}{{splevel=Creature Power}}{{school=Power}}Specs=[Beholder-Anti-Magic-Ray,Power,0H,Innate Ability]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[140yds 90-degree cone](!rounds --aoe @{selected|token_id}|cone|yds|0|140|140|magic|true)}}{{save=None}}SpellData=[w:Beholder Anti Magic Ray,sp:0,pd:-1]{{effects=140-yard range, which covers a 90 degree arc before the creature. No magic (including the effects of the other eyes) will function within that area. Spells cast in or passing through that zone cease to function. The beholder may activate the magical powers of its eyes at will}}{{Use=Point the beholder in the direction to cast before selecting the Area of Effect button to see the area of effect}}'},
+ {name:'Birdcharmer-Charm',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Mesmerize a Victim}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Birdcharmer Charm,Power,0H,Enchantment-Charm]{{components=S}}{{time=[[10]]}}{{range=Line of sight}}{{duration=[While concentrate](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Victim?}|token_id}|Mesmerized|99|0|Mesmerised while watching the snake sway to and fro|chained-heart) and [2d6 rounds](!rounds --removetargetstatus \\amp#64;{target|Who\'s the Victim?|token_id}|Mesmerized --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Victim?|token_id}|Mesmerised still|\\amp#91;[2d6]\\amp#93;|-1|Still mesmerized even though the snake has looked elsewhere|chained-heart) thereafter}}{{aoe=[[1]] creature}}{{save=vs. paralysation negates}}SpellData=[w:Birdcharmer Charm,sp:10,cs:S]{{effects=Some constrictor snakes are known as birdcharmers; these innately magical snakes can mesmerize their prey by swaying slowly and steadily while staring down their victims. Creatures of animal intelligence or less must make a saving throw against paralyzation or be effectively paralyzed for as long as the snake continues to sway, and for 2d6 rounds thereafter.}}'},
+ {name:'Blackrazor-Haste',type:'ItemPower',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Blackrazor casts\nHaste\nas a level 12 caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Blackrazor-Haste,ItemPower,1H,Alteration]{{components=V, S}}{{time=[[3]]}}{{range=[[60]]yds}}{{duration=[[36]] rounds}}{{aoe=[[12]]creatures in a [40ft. cube](!rounds --aoe @{selected|token_id}|square|feet|180|40||magic)}}{{save=None}}{{healing=[Super-Speed](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select who to hurry up|token_id}|Haste|15|-1|Hasted, double attacks, move etc|Strong)}}SpellData=[w:Blackrazor Haste,sp:3,cs:VS]{{effects=When this spell is cast, each affected creature functions at double its normal movement and attack rates. A hasted creature gains a -2 initiative bonus. Thus, a creature moving at 6 and attacking once per round would move at 12 and attack twice per round. Spellcasting and spell effects are not sped up. The number of creatures that can be affected is equal to the caster\'s experience level; those creatures closest to the centre of effect are affected first. All affected by haste must be in the designated area of effect. Note that this spell negates the effects of a slow spell. Additionally, this spell ages the recipient by one year, because of sped-up metabolic processes. This spell is not cumulative with itself or with other similar magic.}}{{materials=A shaving of liquorice root.}}'},
+ {name:'Bright-Sunlight-1-tohit-penalty',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} is suffering\nBright Sunlight}}{{splevel=Penalty}}{{school=Power}}Specs=[Bright Sunlight,Power,0H,Innate Ability]{{components=None}}{{time=[[0]]}}{{range=Self}}{{duration=While in bright sunlight}}{{aoe=The creature}}{{save=None}}SpellData=[w:Bright Sunlight,sp:0,pd:-1]{{effects=If fighting in bright sunlight, this creature suffers a -1 penalty to attack roles}}{{Use=Press [In Bright Sunlight](!rounds --target caster|@{selected|token_id}|Sunlight -1 tohit penalty|99|0|Suffering -1 to hit due to being in bright sunlight|bleeding-eye) to apply penalty, and [In Shade](!rounds --removetargetstatus @{selected|token_id}|Sunlight -1 tohit penalty) to end it}}'},
+ {name:'Chariot-of-Sustarre',type:'Power',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses\nChariot of Sustarre\nas a Power}}{{splevel=Power}}{{school=Evocation}}{{sphere=Elemental (Fire), Creation}}Specs=[Chariot of Sustarre,Power,1H,Evocation]{{components=V,S}}{{range=[[10]] yards}}{{time=[[1]] turn}}{{duration=[12 hours](!rounds --target caster|@{selected|token_id}|Chariot of Sustarre|720|-1|You have a flaming flying chariot, move 24, FL 48|overdrive)}}{{aoe=Special}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 save vs petrification)}}{{reference=PHB p231}}SpellData=[w:Chariot of Sustarre,sp:100,cs:VS,sph:Elemental-Fire|Creation]{{effects=Brings forth a large, flaming chariot pulled by two fiery horses from the elemental plane of Fire in a clap of thunder amid a cloud of smoke.}}'},
+ {name:'Charm-Fascination',type:'Power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nCharm/Fascination\nas a Power}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Charm-Fascination,Power,0H,Enchantment-Charm]{{components=V}}{{time=[[3]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[[1+@{selected|casting-level}]] hours}}{{aoe=[[1]] creature}}{{save=[Negates](!\\amp#13;\\amp#47;r 1d20 save vs. spell for Charm-Fascination)}}{{reference=*The Complete Priest\'s Handbook*, Powers}}{{healing=[Make a Suggestion](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select suggestable target|token_id}|Suggestion|[[60+(60*@{selected|casting-level})]]|-1|Agrees with the Wizard\'s Suggestion and getting on with it|chained-heart)}}SpellData=[w:Charm-Fascination,sp:3,cs:V]{{effects=Works just like the third-level Wizard spell suggestion, except that the priest does not have to use material components to the spell.\nThe DM may define this Power as working one of two ways. Either it can be used in combat (in which case it can be used against only one target at a time), or it cannot be used in combat (in which it can be used against a number of targets equal in HD to two times the Priest\'s experience level).\nIn either case, the Priest can use the ability three times per day. If the target makes his saving throw, he may choose to reject the suggestion, but will not recognize that priestly magic was being used against him.\nThis power is most appropriate to priests of the gods of love, mischief and trickery, music, and peace, but can be given to any priesthood which has an influential position in the society.}}'},
+ {name:'Contaminate-Water',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nContaminate Water\nas a level @{selected|Casting-Level} caster}}{{splevel=Power}}{{school=Alteration}}{{sphere=All}}Specs=[Contaminate-Water,Power,1H,Alteration]{{components=V,S}}{{time=[[1]] round}}{{range=[[30]] yds}}{{duration=Permanent}}{{aoe=[[@{selected|Casting-Level}]] cu.ft.}}{{save=None}}SpellData=[w:Contaminate Water,sp:10,cs:VS,sph:All]{{effects=When cast, this spell makes pure food and water into spoiled, rotten, poisonous, or otherwise contaminated food and water totally unsuitable for eating and drinking. Up to 1 cubic foot of food and drink per level can be thus contaminated. This spoils even holy water; however, it has no effect upon creatures or potions}}'},
+ {name:'Control-undead',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nControl Undead\nas a level @{selected|pr-casting-level} @{selected|class3}}}{{splevel=Power}}{{school=Necromancy}}Specs=[Control-Undead,Power,1H,Necromancy]{{components=V,S,M}}{{time=[[10]]}}{{range=0}}{{duration=Until broken}}{{aoe=Up to [[12]] Undead within line of sight}}{{save=See turning table}}{{reference=PHB p103}}{{damage=[Control It](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first undead|token_id}|Controlled|99|0|Controlled-undead, subservient to @{selected|character_name}|chained-heart)}}SpellData=[w:Control-Undead,sp:10,cs:VSM]{{effects=An ability of Evil Clerics, and Shamen of all persuasions. Attempting to control counts as an action, requiring one round and occurring during the character\'s turn in the initiative order (thus, the undead may get to act before the character can control them). The mere presence of the character is not enough--a touch of drama from the character is important. Speech and gestures are important, so the character must have his hands free and be in a position to speak. However, controlling is not like spellcasting and is not interrupted if the character is attacked during the attempt.\nTo resolve a attempt, look on Table 61. Cross-index the Hit Dice or type of the undead with the level of the character. If there is a number listed, roll 1d20. If the number rolled is equal to or greater than that listed, the attempt is successful. If the letter "T" appears, the attempt is automatically successful without a die roll, and the undead will follow orders if they can. If the letter "D" is given, the controlling makes the undead utterly subservient. A dash (--) means that a priest of that level cannot control that type of undead. A successful controlling affects 2d6 undead. If the undead are a mixed group, the lowest Hit Dice creatures are controlled first.\nOnly one die is rolled regardless of the number of undead the character is attempting to control in a given round. The result is read individually for each type of undead.}}{{material=The Priest\'s holy symbol}}'},
+ {name:'Create-Food-and-Water',type:'Power',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses\nCreate Food and Water\nas a Power}}{{splevel=Power}}{{school=Alteration}}{{sphere=Creation}}Specs=[Create-Food-and-Water,Power,1H,Alteration]{{components=V,S}}{{time=[[1]]turn}}{{range=[[10]] yards}}{{duration=Special}}{{aoe=[[@{selected|casting-level}]]cu.ft.}}{{save=None}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Create-Food-and-Water,lv:3,sp:100,gp:0,cs:VS,sph:Creation]{{effects=Causes food and water to appear.}}'},
+ {name:'Cure-Insanity',type:'Power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Staff of Curing\nCure Insanity}}{{splevel=Magic Item Power}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cure Insanity,Power,1H,Necromancy]{{components=V,M}}{{time=[[4]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=None}}{{reference=DMG p154}}SpellData=[w:Cure Insanity,sp:4,cs:VM]{{effects=*Cure Insanity* reverses the effects of *Feablemind* or *Confusion*, and any similar spells or powers}}'},
+ {name:'Cure-Wounds',type:'Power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Staff of Curing\nCure Wounds}}{{splevel=Magic Item Power}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cure Wounds,Power,1H,Necromancy]{{components=V,M}}{{time=[[8]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=None}}{{reference=DMG p154}}SpellData=[w:Cure Wounds,sp:4,cs:VM]{{effects=*Cure Wounds* cures [3d6+3 HP](!\\amp#13;\\amp#47;gr 3d6+3 HP cured) of damage, but only once per creature per day, and only twice a day in total}}'},
+ {name:'Curtain-of-Blackness',type:'Power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Curtain of Blackness}}{{splevel=Power}}{{school=Conjuration}}Specs=[Curtain of Blackness,Power,1H,Alteration]{{components=V,M}}{{time=[[5]]}}{{range=60 feet}}{{duration=Permanent}}{{aoe=[600 sq. feet](!rounds --aoe @{selected|token_id}|wall|feet|60|||dark)}}{{save=None}}SpellData=[w:Curtain of Blackness,sp:5,cs:VM]{{effects=A veil of total black can be cast that absorbs all light. The curtain of blackness can cover a maximum area of 600 square feet (60\' x 10\', 40\' x 15\', 30\' x 20\'), but it must stretch from ceiling to floor, wall to wall. Typically cast from a *Wand of Conjuration*, the curtain takes two charges to conjure. The veil of total lightlessness can be penetrated only by physical means or magic.}}{{Use=Press the area of effect button, then specify the width and direction to set the location of the wall}}'},
+ {name:'Darkness-10ft-radius',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nDarkness, 10\' Radius\nas a level @{selected|mu-casting-level} caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Darkness-10ft-radius,Power,1H,Alteration]{{components=V, S}}{{time=[[2]]}}{{range=[[@{selected|mu-casting-level}*10]] yds}}{{duration=[[@{selected|mu-casting-level}+10]] rounds}}{{aoe=[10ft. radius (or as cast)](!rounds --aoe @{selected|token_id}|circle|feet|[[@{selected|casting-level}*30]]||20|black)}}{{save=None}}SpellData=[w:Darkness 10ft radius,sp:2,cs:VS]{{effects=This spell causes total, impenetrable darkness in the area of effect. Infravision is useless. Neither normal nor magical light works unless a *Light* or *Continual Light* spell is used. Only *Light* or *Continual Light* work, with *Light* and *Darkness* cancelling out, but *Continual Light* creating light.}}{{materials=A bit of bat fur and either a drop of pitch or a piece of coal.}}'},
+ {name:'Defence-Stance',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} starts\nDefence Stance\nas a level @{selected|level-class1} Dwarven Defender}}{{splevel=Power}}{{school=Dwarven Defender}}Specs=[Defence-Stance,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=[[10]] Rounds}}{{aoe=Self}}{{save=None}}{{healing=[Adopt the Position!](!rounds --target caster|@{selected|token_id}|Defence-stance|10|-1|Defence Stance, 1/2 damage, +2 on saves, 50% move|overdrive)}}SpellData=[w:Defence Stance,sp:0,cs:S]{{effects=This Dwarven Defender gets [[{ceil(@{selected|level-class1}/4),3}kl1]] Defensive Stances a Day. This lasts for [[10]] rounds and can be invoked instantly. While they have Defensive staff active, they suffer only **half damage** from all forms of physical damage, a +[[2]] on **saving throws** and a [[50]]% **penalty to their move**}}'},
+ {name:'Defiance',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nDefiance of Restriction or Obstacle\nas a Power}}{{splevel=Power}}{{school=Alteration}}Specs=[Defiance,Power,0H,Alteration]{{components=V}}{{time=[[1]]}}{{range=[[0]]}}{{duration=[Unlimited](!rounds --target caster|@{selected|token_id}|Defiance-Power|99|0|Defying a natural Restriction or Obstacle|aura)}}{{aoe=The caster}}{{save=None}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Defiance,sp:9,cs:V]{{effects=The priest can simply ignore some aspect of the physical world which normally slows, impedes, or prevents passage. This is similar to the Druidic power, *Pass Without Trace*. The Obstacle or restriction that can be defied varies with the Priesthood.}}'},
+ {name:'Detect-Flawed-Stonework',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Unsafe Walls, Ceilings \\amp Floors\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect Flawed Stonework,Power,1H,Divination]{{components=S}}{{time=1 round}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect Flawed Stonework,lv:0,sp:10,cs:S]{{effects=Tunnelers of great skill can detect unsafe construction of walls, ceilings and floors on a [1-7 on d10](!\\amp#13;\\amp#47;r 1d10\\lt7) when within 10 feet of the location.}}'},
+ {name:'Detect-Illusions',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Detect Illusions}}{{splevel=Power}}{{school=Divination}}Specs=[Detect Illusions,Power,0H,Divination]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Special}}{{aoe=Line of Sight}}{{save=None}}SpellData=[w:Detect Illusions,sp:0]{{desc=Those with a high Intelligence score, with granted powers, or with magic items that grant the ability, can detect illusions up to a certain level. The DM will determine the circumstances based on the source of the power used and the type of illusion (if such exists at all!)}}'},
+ {name:'Detect-New-Construction',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect New Passage/Tunnel Construction\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect New Construction,Power,1H,Divination]{{components=S}}{{time=[[0]]}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect New Construction,lv:0,sp:0,cs:S]{{effects=Miners of great skill, while underground, can detect the new construction of a tunnel or passage when within 10 feet of the location (and they can determine their approximate depth below the surface at any time).\nHobgoblins: on a [1-4 on d10](!\\amp#13;\\amp#47;r 1d10\\lt4) \nOthers: on a [1-5 on d6](!\\amp#13;\\amp#47;r 1d6\\lt5) }}'},
+ {name:'Detect-Shifting-Walls',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Sliding/Shifting Walls or Rooms\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect Shifting Walls,Power,1H,Divination]{{components=S}}{{time=[[0]]}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect Shifting Walls,lv:0,sp:0,cs:S]{{effects=Miners of great skill, while underground, can detect sliding or shifting walls or rooms when within 10 feet of the location (and they can determine their approximate depth below the surface at any time).\nHobgoblins: on a [1-4 on d10](!\\amp#13;\\amp#47;r 1d10\\lt4) \nOthers: on a [1-4 on d6](!\\amp#13;\\amp#47;r 1d6\\lt4) }}'},
+ {name:'Detect-Slope',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Passage Grade or Slope\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect Slope,Power,1H,Divination]{{components=S}}{{time=1 round}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect Slope,lv:0,sp:10,cs:S]{{effects=Miners of great skill, while underground, can detect the grade or slope of a passage on a [1-5 on d6](!\\amp#13;\\amp#47;r 1d6\\lt5) when within 10 feet of the location (and they can determine their approximate depth below the surface at any time).\nStout halflings on a [1-3 on d4](!\\amp#13;\\amp#47;r 1d4\\lt3)\nHobgoblins on a [1-4 on d10](!\\amp#13;\\amp#47;r 1d10\\lt4)\nOthers on a [1-5 on d6](!\\amp#13;\\amp#47;r 1d6\\lt5)}}'},
+ {name:'Detect-Stonework-Traps',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Stonework Traps, Pits \\amp Deadfalls\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect Stonework Traps,Power,1H,Divination]{{components=S}}{{time=[[0]]}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect Stonework Traps,lv:0,sp:0,cs:S]{{effects=Miners of great skill, while underground, can detect stonework traps, pits \\amp deadfalls on a [1-3 on d6](!\\amp#13;\\amp#47;r 1d6\\lt3) when within 10 feet of the location (and they can determine their approximate depth below the surface at any time).}}'},
+ {name:'Determine-Depth-Underground',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Approximate Depth Underground\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Determine Depth Underground,Power,1H,Divination]{{components=S}}{{time=1 round}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Determine Depth Underground,lv:0,sp:10,cs:S]{{effects=Miners of great skill, while underground, can determine their approximate depth underground.\nDwarves on a [1-3 on d6](!\\amp#13;\\amp#47;r 1d6\\lt3).\nGnomes on a [1-4 on d6](!\\amp#13;\\amp#47;r 1d6\\lt4).}}'},
+ {name:'Determine-Direction-Underground',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Approximate Direction Underground\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Determine Direction Underground,Power,1H,Divination]{{components=S}}{{time=1 round}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|light|true)}}{{duration=1 round}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Determine Direction Underground,lv:0,sp:10,cs:S]{{effects=Tunnelers of great skill, while underground, can determine their approximate direction of travel underground on a [1-3 on d6](!\\amp#13;\\amp#47;r 1d6\\lt3).}}'},
+ {name:'Divine-Favour',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Divine Favour}}Specs=[Divine-Favour,Power,1H,Alteration]{{Range=[[30]]ft}}{{Speed=0}}SpellData=[w:Divine Favour,sp:0,cs:None]{{desc=@{selected|casting-name} calls on a [Divine Favour](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select Beneficiary|token_id}|Divine-favour|6|-1|In Divine Favour +[[4]] to hit if within [[30]]ft of @{selected|casting-name}|fist) for someone giving +[[4]] to hit for [[6]] rounds as long as they are within [[30]]ft of @{selected|token_name}}}'},
+ {name:'Djinni-Whirlwind',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Whirlwind}}Specs=[Djinni-Whirlwind,Power,0H,Innate Ability]{{Speed=[[1]]}}{{save=Vs Breath Weapon to halve}}{{Recharge=[Start recharging](!rounds --target caster|@{selected|token_id}|AE-Whirlwind|\\amp#91;[3+1d3]\\amp#93;|-1|Whirlwind building|stopwatch)}}SpellData=[w:Djinni-Whirlwind,sp:1,cs:S]{{desc=A genie can [Create a Whirlwind](!rounds --target caster|@{selected|token_id}|Djinni-Whirlwind-building|10|-1|Whirlwind building, cannot do damage yet|stopwatch), which it can ride or even direct at will from a distance. The whirlwind is a cone-shaped spiral, measuring up to 10 feet across at its base, 40 feet across at the top, and up to 70 feet in height (the djinni chooses the dimensions). Its maximum speed is 18, with maneuverability class A. The whirlwind\'s base must touch water or a solid surface, or it will dissolve. It takes a full turn for the whirlwind to form or dissolve. During that time, the whirlwind inflicts no damage and has no other effect. The whirlwind lasts as long as the djinni concentrates on it, moving at the creature\'s whim.\nIf the whirlwind strikes a non-aerial creature with fewer than 2 Hit Dice, the creature must make a saving throw vs. breath weapon for each round of contact with the whirlwind, or be swept off its feet, battered, and killed. Hardier beings, as well as aerial or airborne creatures, take 2d6 points of damage per round of contact with the whirlwind.\nA djinni can ride its whirlwind and even take along passengers, who (like the djinni) suffer no damage from the buffeting winds. The whirlwind can carry the genie and up to six man-sized or three genie-sized companions.}}'},
+ {name:'Do-1HP-care',type:'',ct:'0',charge:'uncharged',cost:'0',body:'!setattr --silent --charid @{selected|character_id} --spell-cast|Do-day-care\n!token-mod --ignore-selected --ids @{target|Tend to which creature?|token_id} --set bar3_value|+1! --report control|"{name} is healed by 1 from {bar3_value:change}HP"\n!magic --cast-again power|@{selected|token_id}|Do-1HP-care'},
+ {name:'Do-1st-aid',type:'',ct:'0',charge:'uncharged',cost:'0',body:'!setattr --silent --charid @{selected|character_id} --spell-cast|Do-1st-aid\n!token-mod --ignore-selected --ids @{target|Tend to which creature?|token_id} --set bar3_value|+[[?{How much First Aid?|1d3}]]! --report control|"{name} is healed from {bar3_value:change}HP"\n!magic --cast-again power|@{selected|token_id}|Do-1st-aid'},
+ {name:'Do-2HP-care',type:'',ct:'0',charge:'uncharged',cost:'0',body:'!setattr --silent --charid @{selected|character_id} --spell-cast|Do-2HP-care\n!token-mod --ignore-selected --ids @{target|Tend to which creature?|token_id} --set bar3_value|+2! --report control|"{name} is healed by 2 from {bar3_value:change}HP"\n!magic --cast-again power|@{selected|token_id}|Do-2HP-care'},
+ {name:'Do-3HP-care',type:'',ct:'0',charge:'uncharged',cost:'0',body:'!setattr --silent --charid @{selected|character_id} --spell-cast|Do-3HP-care\n!token-mod --ignore-selected --ids @{target|Tend to which creature?|token_id} --set bar3_value|+3! --report control|"{name} is healed by 3 from {bar3_value:change}HP"\n!magic --cast-again power|@{selected|token_id}|Do-3HP-care'},
+ {name:'Dracolisk-Breath',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Dracolisk Spits Acid}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Dracolisk-Breath,Power,0H,Innate Ability]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[30ft strem, 5ftwide](!rounds --aoe @{selected|token_id}|bolt|feet|0|30|5|acid|true)}}{{save=vs. Breath Weapon for half damage}}{{damage=[4d6 HP acid damage](!\\amp#13;\\amp#47;gmroll 4d6 acid damage from Dracolisk Breath)}}SpellData=[w:Dracolisk Breath,sp:0,pd:3]{{effects=A dracolisk can spit a stream of acid 5 feet wide and up to 30 feet away. The acid causes 4d6 points of damage, half-damage if a successful saving throw vs. breath weapon is rolled. The dracolisk can spit up to three times per day.}}{{Use=Select the Area of Effect button to see the area of effect and then roll damage for each creature in the area}}'},
+ {name:'Druids-Identify',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Identify Plants, Animals \\amp Pure Water as a Druid}}Specs=[Druids-Identify,Power,0H,Divination]{{Speed=[[10]]}}{{save=None}}SpellData=[w:Druids-Identify,sp:10,cs:S]{{desc=Identify all plants, animals and pure water with 100% accuracy.}}'},
+ {name:'Dryad-Charm-Person',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{splevel=Level 1 Wizard}}%{MU-Spells-DB|Charm-Person}{{title=The Dryad uses\nCharm Person\nas a Power}}Specs=[Dryad Charm Person,Power,0H,Enchantment-Charm]{{save=vs. spell at a penalty of -3 (special for Dryad power) Negates}}SpellData=[w:Charm-Person,lv:1,sp:1,gp:0,cs:VS]{{components=None}}'},
+ {name:'Duergar-Enlarge',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nEnlarge\nas a Power at level [[2*@{selected|casting-level}]]}}{{splevel=Power}}{{school=Alteration}}Specs=[Duergar Enlarge,Power,1H,Alteration]{{components=V, S}}{{time=[[1]]}}{{range=Caster}}{{duration=[ @{selected|casting-level}0 Rounds](!rounds --target caster|@{selected|token_id}|Enlarge|[[10*@{selected|casting-level}]]|-1|Enlarged, Damage x [[1+(@{selected|casting-level}/5)]]|overdrive)}}{{aoe=Caster}}{{save=None}}{{reference=Complete Dwarves Handbook}}SpellData=[w:Duergar Enlarge,lv:1,sp:1,gp:0,cs:VS]{{effects=Causes instant growth of a Duergar (Gray Elf) casting it, increasing both size and weight. The Power works at double the casting level of the caster, but can only affect the caster and what they are wearing or using}}'},
+ {name:'Duergar-Invisibility',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nInvisibility\nas a Power at level [[2*@{selected|casting-level}]]}}{{splevel=Power}}{{school=Illusion/Phantasm}}Specs=[Duergar Invisibility,Power,1H,Illusion-Phantasm]{{components=V, S}}{{time=[[2]]}}{{range=Caster}}{{duration=[ Until attack or 24 hours](!rounds --target caster|@{selected|token_id}|Invisibility|99|0|Invisible except slight haze, 4 bonus to AC \\amp saves, until attack|half-haze)}}{{aoe=Caster}}{{save=None}}{{reference=Complete Dwarves Handbook}}SpellData=[w:Duergar Invisibility,lv:2,sp:2,gp:0,cs:VS]{{effects=Causes the Duergar (Gray Elf) casting it to become invisible, along with everything they are wearing, undetectable by normal vision or infravision. Not magically silenced. The Power works at double the casting level of the caster}}'},
+ {name:'Elf-Detect-Secret-Doors',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nDetect Secret Doors \\amp Concealed Portals\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Detect Secret Doors,Power,1H,Divination]{{components=S}}{{time=[[0]]}}{{range=Touch}}{{duration=While searching}}{{aoe=Caster}}{{save=None}}{{reference=PHB Chapter 2}}SpellData=[w:Detect Secret Doors,lv:0,sp:0,cs:S]{{effects=Secret doors (those constructed so as to be hard to notice) and concealed doors (those hidden from sight by screens, curtains, or the like) are difficult to hide from elves. Merely passing within 10 feet of a concealed door gives an elven character a one-in-six chance (roll a [1 on 1d6](!\\amp#13;\\amp#47;r 1d6\\lt1)) to notice it. If actively searching for such doors, elven characters have a one-in-three chance (roll a [1 or 2 on 1d6](!\\amp#13;\\amp#47;r 1d6\\lt2)) to find a secret door and a one-in-two chance (roll a [1, 2, or 3 on 1d6](!\\amp#13;\\amp#47;r 1d6\\lt3)) to discover a concealed portal.}}'},
+ {name:'Etherial-Travel-Self',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} is using\nEtherial Travel (self)\nas a power as a level @{selected|casting-level} caster}}{{splevel=Level 9 Wizard}}{{school=Evocation}}Specs=[Etherial Travel self,Power,1H,Evocation]{{components=V,M}}{{time=9}}{{range=Caster}}{{duration=Special}}{{aoe=Self}}{{save=None}}{{reference=DMG p153}}SpellData=[w:Etherial Travel self,sp:9,cs:VM]{{effects=Unlike the spell *Astral Spell*, transfers the caster\'s *material body* into the Etherial Plane, meaning they can travel materially through the Etherial Plane and emerge elsewhere on the Material Plane. Of course, as the caster\'s material body actually becomes Etherial, no silver thread remains joining the two as the two are one.}}'},
+ {name:'Fire-Mephit-Flame-Breath',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Fire Mephit breathes out Flame}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Fire Mephit Flame,Power,0H,Breath Weapon]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=Jet 1 creature in [15ft x 1ft](!rounds --aoe @{selected|token_id}|bolt|feet|0|15|1|fire) or Fan for [5ft x 120deg arc](!rounds --aoe @{selected|token_id}|cone|feet|0|5|8|fire)}}{{save=Jet: save vs. breath for half damage.\nFan: none}}{{damage=Jet automatic hit [1d8+1](!\\amp#13;\\amp#47;gmroll 1d8+1 fire damage, save to half) or Fan [[4]]HP no save}}SpellData=[w:Fire Mephit Flame,sp:0,cs:None,pd:3]{{effects=Fire mephits may use their breath weapon three times a day. It has two forms. The first is a flame jet 15 feet long and 1-foot wide. This jet automatically hits one target, of the mephit\'s choosing, for ld8+1 points of damage (half if saving throw is successful). The second form is a fan of flame covering a 120 arc directly in front of the mephit to a distance of 5 feet. Any creature in the arc suffers 4 points of damage, no saving throw allowed.}}{{Use=Select the desired flame shape (Jet or Fan) using the Area of Effect buttons, then do the appropriate damage based on saving throw or otherwise}}'},
+ {name:'Fire-Resistance',type:'Power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} has\nFire Resistance\nas a Power cast at @{selected|Casting-Level} level}}{{splevel=Power}}{{school=Alteration/Protection}}Specs=[Fire-Resistance,Power,1H,Alteration-Protection]{{components=None}}{{time=[[5]]}}{{range=0}}{{duration=Continuous}}{{aoe=Creature with Power}}{{save=None}}SpellData=[w:Fire-Resistance,lv:1,sp:5,gp:0]{{effects=Those with this power are totally immune to the effects of normal fires—torches, flaming oil, bonfires, etc. Very large and hot fires, molten lava, hell-hound breath, or a wall of fire spell will cause 10 hit points of damage per round if the wearer is directly within the conflagration.\nExceptionally hot fires such as red-dragon breath, pyrohydra breath, fireballs, flame strike, fire storm, etc., are saved against with a +4 bonus to the die roll, and all damage dice are calculated at -2 per die, but each die is never less than 1 in any event. As a rule of thumb, consider very hot fires as those that have a maximum initial exposure of up to 24 hit points, those of exceptional heat (25 or more hit points)}}'},
+ {name:'Firedrake-Breath',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Firedrake uses\nFire Breath}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Firedrake-Breath,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[60ft cone, 10ft dia. at end](!rounds --aoe @{selected|token_id}|cone|feet|0|60|10|fire|true)}}{{save=[Halves](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Breath Weapon)}}SpellData=[w:Firedrake Breath,sp:0,cs:S]{{effects=The firedrake\'s primary attack is its breath weapon (fire), which it can use up to five times daily. The fire forms a cone from the snout of the dragonet to a 10\' diameter circle at the extreme end of its 60\' range, and causes 2-16 points on all affected (save vs. breath weapon for half damage).\nThe dragonet\'s blood burns fiercely in air, as there is a high phosphorous content to the blood. In fact, the fire-breathing of these creatures is actually the voluntary expelling of a jet of its pyrophoric blood. Because of the flammability of the dragon\'s blood, blunt weapons such as staves or clubs are less dangerous than those which cause blood loss. Any creature making a successful slashing or piercing attack on a firedrake must save vs. breath weapon, or take 1-2 points of fire damage.}}'},
+ {name:'Follow-the-Standard',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses\nFollow the Standard}}{{splevel=Power}}{{school=Combat}}Specs=[Follow the Standard,Power,1H,Combat]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=[While alive](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is Fortified?|token_id}|Follow the Standard|99|0|Motivated by the Standard - +1 to attack \\amp morale|flying-flag)}}{{aoe=[60 yards radius](!rounds --aoe @{selected|token_id}|circle|yards|0|120|120|light|true)}}{{save=None}}SpellData=[w:Follow the Standard,sp:0,pd:-1]{{effects=If a subchief is present, there is a 40% chance the creatures will be fighting around a standard. The presence of this standard increases attack rolls and morale by +1 for all of those creatures within 60 yards.}}{{Use=Use the Area of Effect button to display the radius. Then use the Duration button to apply the *Flying Flag* status marker to those who benefit from the bonus.}}'},
+ {name:'Gaseous-Form',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nGaseous Form\nas a level @{selected|casting-level} caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Gaseous-Form,Power,1H,Alteration]{{components=S}}{{time=[[1]]}}{{range=[[0]]}}{{duration=4+1d4 turns}}{{aoe=The caster}}{{save=None}}{{healing=[Go Gaseous](!rounds --target caster|@{selected|token_id}|Gaseous-Form|\\amp#91;[4+1d4]\\amp#93;|-1|In gaseous form, drift at 3, dmg by magic fire/lightning only|half-haze)}}SpellData=[w:Gaseous Form,sp:1,cs:S]{{effects=This power grants the same effect as consuming a Potion of Gaseous Form.\nThe individual causes his body, as well as anything he\'s carrying or wearing, to become gaseous. The gaseous form is able to flow at a base speed of 3/round. (A gust of wind spell, or even normal strong air currents, will blow the gaseous form at air speed.)\nThe gaseous form is transparent and insubstantial. It wavers and shifts, and can\'t be harmed except by magical fire or lightning, which do normal damage. A whirlwind inflicts double damage upon a creature in gaseous form. When in such condition the individual is able to enter any space that is not airtight-even a small crack or hole that allows air to penetrate also allows entry by a creature in gaseous form. The effects last the entire duration (4+1d4turns).}}'},
+ {name:'Gate-Mephit',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Mephit *gates* another Mephit}}{{splevel=Power}}{{school=Conjuration/Summoning}}Specs=[Gate-Mephit,Power,0H,Conjuration-Summoning]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=1 creature}}{{save=None}}SpellData=[w:Gate Mephit,sp:0,cs:None]{{effects=Mephits of different types can *gate* another Mephit to join them, once per hour. Different types of Mephit can *gate* specific other types, at varying rates of success:\n**Fire Mephit:**\n25% 1 Fire/Lava/Smoke/Steam\n**Ice Mephit:**\n25% 1 Ice/Mist\n**Lava Mephit:**\n25% 1-2 Fire/Lava/Smoke/Steam\n**Mist Mephit:**\n20% 1-2 Ice/Mist\n**Smoke Mephit:**\n20% 1-2 Fire/Lava/Smoke/Steam\n**Steam Mephit:**\n30% 1-2 Fire/Lava/Smoke/Steam}}'},
+ {name:'Ghast-Stench',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses\nGhast Stench}}{{splevel=Power}}{{school=Innate Power}}Specs=[Ghast Stench,Power,1H,Innate]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=[Nausious](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is Nauseous?|token_id}|Nauseous-2|99|0|Made nauseous by Ghast stink, 2 penalty to attacks|half-haze) while within area of effect}}{{aoe=[10ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|20|20|acid|true)}}{{save=vs. poison negates}}SpellData=[w:Ghast Stench,sp:0,pd:-1]{{effects=A Ghast has a ghastly stench that causes those within 10ft to save vs. poison or start retching and being nauseous, causing them to attack at a penalty of 2}}{{Use=Use the Area of Effect button to display the circle. Then use the Duration button to apply the *Nauseous* status marker to those who fail their saving throw. The resulting effect will alter the to-hit probability for the duration}}'},
+ {name:'Ghost-Fear',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Fear of the Ghost}}{{splevel=Innate Ability}}{{school=Necromancy}}Specs=[Ghost-Fear,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[60yds, Line of Sight](!rounds --aoe @{selected|token_id}|circle|yards|0|120|120|dark|true)}}{{duration=[2d6 turns](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who sees the Ghost?|token_id}|Ghost Fear|\\amp#91;[10\\amp42;2d6]\\amp#93;|-1|Fleeing at maximum move away from the Ghost!|screaming\\amp#13;!modattr --charid \\amp#64;{target|Who sees the Ghost?|character_id} --age|10 --fb-header _CHARNAME_ grows older --fb-content _CHARNAME_ has aged by _TCUR0_ and is now _CUR0_ years old) \\amp age permanently}}{{aoe=Line of Sight}}{{save=Negates}}SpellData=[w:Ghost Fear,sp:0,pd:-1]{{effects=The mere sight of a Ghost within 60yds causes any humanoid being to age 10 years and flee in panic for 2-12 (2d6) turns unless a saving throw versus spell is made.}}{{Use=Select the Range button to identify those tokens in range of the effect. Then select the Duration button and select each character that fails to save, using the button that appears in the chat window to prompt for you to select each in turn.}}'},
+ {name:'Giant-Skeleton-Fireball',type:'Power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nFireball\nas a level 8 caster}}{{splevel=Power}}{{school=Evocation}}Specs=[Fireball,Power,0H,Evocation]{{components=None}}{{time=[[3]]}}{{range=[[10+(10*{10,@{selected|casting-level}}kl1)]]yds}}{{duration=Instantaneous}}{{aoe=[20ft. radius](!rounds --aoe @{selected|token_id}|circle|feet|270|40||fire)}}{{save=vs. spell (add situational dex mods) for half damage}}{{reference=PHB p149}}{{damage=[8d6](!\\amp#13;\\amp#47;r 8d6) (halved if save)}}{{damagetype=Fire}}SpellData=[w:Giant Skeleton Fireball,lv:3,sp:3]{{effects=The giant skeleton reaches into its chest and pulls forth flame, which it hurls.It blossoms into a fireball. Creatures failing their saving throws each suffer full damage from the blast. Those who roll successful saving throws manage to dodge, fall flat, or roll aside, each receiving half damage.}}'},
+ {name:'Gorgon-Breath',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Gorgon uses\nParalysis Breath}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Gorgon-Breath,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[60ft cone, 5ft at mouth,20ft dia. at end](!rounds --aoe @{selected|token_id}|cone|feet|0|60|20|acid|true)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Petrification) vs. Petrification}}{{damage=[Petrify Them](!rounds --addtargetstatus \\amp#64;{target|Who is petrified?|token_id}|Petrified|99|0|Petrified by Gorgon Breath|sleepy)}}SpellData=[w:Gorgon Breath,sp:0,pd:4]{{effects=Four times per day gorgons can make a breath weapon attack (their preferred means of attack). Their breath shoots forth in a truncated cone, five feet wide at the base and 20 feet wide at its end, with a maximum range of 60 feet. Any creature caught in this cone must roll a saving throw vs. petrification. Those who fail are turned to stone immediately!}}'},
+ {name:'Gully-Dwarf-Grovel',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nGrovel\n}}{{splevel=Skill}}{{school=Power}}Specs=[Gully-Dwarf-Grovely,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Self}}{{duration=Indefinate}}{{aoe=The character}}{{save=None}}SpellData=[w:Gully Dwarf Grovel,sp:0,cs:S]{{effects=If attacked (or at any other time that it might seem beneficial) a Gully Dwarf will grovel and whine in an attempt to avoid injury (probably only to later lie, steal and cheat their way out of the situation). The effectiveness of the grovel will be determined by the DM based on the player\'s role-playing, circumstances, and/or the roll of the dice.}}'},
+ {name:'Hairy-Spider-Poison',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Hairy Spider Poison}}{{splevel=Innate Ability}}{{school=Poison}}Specs=[Hairy-Spider-Poison,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Bite}}{{duration=1d4+1 rounds}}{{aoe=Bitten creature}}{{save=None}}{{damage=[Bite](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who has been poisoned?|token_id}|Hairy-Spider-Poison|\\amp#91;[1d4+1]\\amp#93;|-1|Poisoned, Thac0 \\amp AC 1 worse, DX -3|death-zone)}}SpellData=[w:Hairy Spider Poison,sp:0,cs:S]{{effects=This creature can use Hairy Spider poison. Victims receive a +2 bonus to saving throws vs. the hairy spiders\' weak poison. If the saving throw fails, the victim\'s AC and attack rolls are penalized by 1, and Dexterity is penalized by -3 with respect to Dexterity checks. These effects begin one round after the bite and last for 1d4+1 rounds.}}'},
+ {name:'Hide-in-Shadows',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nHide in Shadows\nas a level @{selected|level-class4} @{selected|class4}}}{{splevel=Skill}}{{school=Thieving}}Specs=[Hide-in-Shadows,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Self}}{{duration=Until attack}}{{aoe=The character}}{{save=None}}{{healing=[Hide in Shadows](!rounds --target caster|@{selected|token_id}|Hide-in-Shadow|99|0|Hiding in Shadows, DM determine success, chance @{selected|hst}pct.|ninja-mask)}}SpellData=[w:Hide in Shadows,sp:0,cs:S]{{effects=The character attempts to move into the shadows and move unseen. This may or may not be successful, and depends on their skill. The DM determines success or otherwise but does not tell the player until it becomes relevant to the character.}}'},
+ {name:'Hide-in-Woods',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}}{{title=@{selected|casting-name} uses\nHide in Woods\nas a Power}}{{splevel=Power}}{{school=Power}}Specs=[Hide in Woods,Power,1H,Abjuration]{{components=S}}{{time=1 round}}{{range=0}}{{duration=As long as actively hiding}}{{aoe=Caster}}{{save=None}}{{reference=Complete Book of Gnomes \\amp Halflings}}SpellData=[w:Hide in Woods,lv:0,sp:10,cs:S]{{effects=The ability to hide in woods with a chance equal to a thief of the same level’s hide in shadows ability (as per 1e rules, as 2e does not have fixed chances per level).\nThese are:}}'},
+ {name:'Hold-Breath',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Hold Breath}}{{splevel=Innate Ability}}{{school=Innate Ability}}Specs=[Hold-Breath,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Special}}{{aoe=Self}}{{save=None}}{{healing=[Hold Breath](!rounds --target caster|@{selected|token_id}|Hold-Breath|\\amp#63;{How many minutes can breath be held?}|-1|Holding Breath|sleepy)}}SpellData=[w:Hold Breat,sp:0,cs:S]{{effects=This creature is able to hold its breath for an unusually long time. For normal rules on holding breath, see the PHB.}}'},
+ {name:'Hypnosis',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Hypnosis}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Hypnosis,Power,0H,Enchantment-Charm]{{components=S}}{{time=[[1]]}}{{range=Line of sight}}{{duration=[Until Caster Breaks](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Victim?|token_id}|Hypnotised|99|0|Hypnotised, do whatever they want|chained-heart) or [1d6 turns](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Victim?|token_id}|Hypnotised|\\amp#91;[10*1d6]\\amp#93;|-1|Hypnotised, do whatever they want|chained-heart)}}{{aoe=[[1]] creature}}{{save=vs. paralysation negates}}SpellData=[w:Hypnosis,sp:1,cs:S]{{effects=Many humans and animals attack heways on sight, but it can defend itself with its hypnotic stare, which has a powerful effect; any creature failing a saving throw vs. paralyzation will follow the heway to its lair and allow itself to be devoured. The heway sometimes uses this stare simply to immobilize a menacing creature. It then leaves the area while the hypnotized creature remains stationary for 1d6 turns.}}'},
+ {name:'Ice-Mephit-Volley',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Ice Mephit uses\nIce Shard Volley}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Ice-Mephit-Volley,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[15ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|15|5|cold|true), 1 creature only}}{{save=[Halves](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Breath Weapon) vs. Breath Weapon}}{{damage=[1d6](!\\amp#13;\\amp#47;gmroll 1d6) save to half}}SpellData=[w:Ice Mephit Volley,sp:0,cs:S]{{effects=Ice mephits may breathe a volley of ice shards three times per day. This volley automatically hits a single victim within 15 feet of the mephit. Damage is 1d6, halved if the victim rolls a successful saving throw.}}'},
+ {name:'Incite-Rage',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nIncite Berserker Rage\nas a Power}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Incite-Rage,Power,1H,Enchantment-Charm]{{components=VS}}{{time=[[10]]}}{{range=[[0]]}}{{duration=[6 turns](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who to Incite to Rage?|token_id}|Incite-Rage|60|-1|Raging with +2 on attacks and damage|aura)}}{{aoe=Creature touched}}{{save=None}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Incite-Rage,sp:10,cs:VS]{{effects=allows a priest to inspire a fighter (anyone belonging to the warrior class) to a state like berserker rage. The warrior must be willing to have this war-blessing bestowed upon him.\nIt takes one round for a priest to incite a single warrior to berserker rage; the rage last six turns. A priest can use this power on any number of warriors per day, one at a time. A warrior may only be incited to berserker rage once per day; even if a different priest tries it on him, it cannot incite a warrior to a second rage in the same day.\nThe rage isn\'t identical to the abilities of the true berserker (see the description for the berserker in The Complete Fighter\'s Handbook). However, it does give the warrior a +2 to hit and damage for the duration of the rage. While enraged, the warrior cannot flee from a fight; he cannot leave the field of battle until no enemies face him. Once he does leave the field of battle, he can choose whether or not he will emerge from the rage or sustain it; a warrior would sustain it if he felt that another fight was likely to take place soon. When he emerges from the rage, the warrior takes no extra damage or ill effects.\nThis power is most appropriate to priests of the god of war.}}'},
+ {name:'Indomitable',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Indomitable\n@{selected|token_name} can Save Again}}{{splevel=Innate Power}}{{school=Alteration}}Specs=[Indomitable,Power,1H,Alteration]{{components=S}}{{time=[[0]] and in parallel with other activity}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=The creature}}{{save=None)}}SpellData=[w:Indomitable,sp:0,cs:S]{{effects=This creature can choose to re-roll a failed saving throw due to his Indomitable nature}}'},
+ {name:'Inspire-Fear',type:'Power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nInspire Fear\nas a Power}}{{splevel=Power}}{{school=Illusion/Phantasm}}Specs=[Inspire-Fear,Power,1H,Illusion-Phantasm]{{components=V, S}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]] rounds}}{{aoe=[60ft. cone, 30ft. at end, 5ft. at base](!rounds --aoe @{selected|token_id}|cone|yards|0|20|10|magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{damage=[Frighten them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Inspire-Fear|[[@{selected|casting-level}]]|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming)}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Inspire-Fear,sp:4,cs:VS]{{effects=A priest with this power can use it twice per day, and is most appropriate to priests of gods with dark or fearsome aspects: Death, for example.\nSends forth invisible cone of terror. Creatures within area of effect to turn away from the caster and flee.}}'},
+ {name:'Jims-Fear',type:'ItemPower',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFear\nas a level @{selected|Casting-Level} caster}}{{splevel=Power}}{{school=Illusion/Phantasm}}Specs=[Jims-Fear,ItemPower,1H,Illusion-Phantasm]{{components=V, S}}{{time=[[4]]}}{{range=[[0]]}}{{duration=1d4 rounds}}{{aoe=[60ft. cone, 30ft. at end, 5ft. at base](!rounds --aoe @{selected|token_id}|cone|yards|0|20|10|magic)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{damage=[Frighten them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Fear|[[@{selected|casting-level}]]|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming)}}SpellData=[w:Jims Fear,sp:4,cs:VS]{{effects=Sends forth invisible cone of terror. Creatures within area of effect to turn away from the caster and flee. Affected creatures are likely to drop whatever they are holding; base chance is [[60]]% at 1st level/1HD, each level/HD above reduces probability by [[5]]%. Creatures affected flee at fastest rate for Duration. Undead and successful saves vs. spell are not affected.}}{{materials=Either the heart of a hen or a white feather.}}'},
+ {name:'Jims-Find-Traps',type:'ItemPower',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nFind Traps\nas a level @{selected|Casting-Level} caster}}{{splevel=Power}}{{school=Divination}}{{sphere=Divination}}Specs=[Jims-Find-Traps,ItemPower,1H,Divination]{{components=V,S}}{{time=[[5]]}}{{range=[[30]] yards}}{{duration=[[3]] turns}}{{aoe=[10ft path to range](!rounds --aoe @{selected|token_id}|bolt|feet|0|90|10|magic) in direction caster is facing}}{{save=None}}SpellData=[w:Jims Find Traps,sp:5,cs:VS]{{effects=All traps, normal or magical become visible to the caster. "Traps" includes alarms. Traps meet 3 criteria: can inflict a sudden or unexpected result; spellcaster would view result as undesirable or harmful; and result specifically intended as such by creator. Caster leans general nature of trap but not exact effect or how to disarm it, but can get sense of what might trigger it. Note - an Ambush is not a trap.}}'},
+ {name:'Jims-Levitation',type:'ItemPower',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Jim casts\nLevitate\nas a level 1 caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Jims-Levitation,ItemPower,1H,Alteration]{{components=V, S}}{{time=[[2]]}}{{range=Wielder of Jim}}{{duration=[[1]] turn}}{{aoe=[[1]] creature or object}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{healing=[Levitate](!rounds --target caster|@{selected|token_id}|Levitate|10|-1|Levitating vertical not horizontal, minuses on missile fire|fluffy-wing)}}SpellData=[w:Jims Levitation,sp:2,cs:VS]{{effects=Subject to a maximum weight limit of [[100*@{selected|casting-level}]] pounds. Wielder can move vertically up or down at a movement rate of [[2]] per round. This spell does not empower horizontal movement, but the recipient could push along the face of a cliff, for example, to move laterally. The spellcaster can cancel the spell as desired. If the subject of the spell is unwilling, or the object is in the possession of a creature, a saving throw vs. spell is allowed to determine if the levitate spell affects it.\nOnce cast, the spell requires no concentration, except when changing height. A levitating creature attempting to use a missile weapon finds himself increasingly unstable; the first attack has an attack roll penalty of [[0-1]], the second [[0-2]], the third [[0-3]], etc., up to a maximum of [[0-5]]. A full round spent stabilising allows the creature to begin again at [[0-1]]. Lack of leverage makes it impossible to cock a medium or heavy crossbow)}}{{materials=Jim the Sunblade}}'},
+ {name:'Jims-Locate-Object',type:'ItemPower',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Jim the Sunblade casts\nLocate Object\nas a level 6 caster}}{{splevel=Power}}{{school=Divination}}{{sphere=Divination}}Specs=[Jims-Locate-Object,ItemPower,1H,Divination]{{components=V,S}}{{time=[[1]] turn}}{{range=[120 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|240||magic|true)}}{{duration=[[8]] hours}}{{aoe=[[1]] object}}{{save=None}}SpellData=[w:Jims Locate Object,sp:1,cs:VS]{{effects=This spell helps locate a known or familiar object. The priest casts the spell, slowly turns, and will sense when he is facing in the direction of the object to be located, provided the object is within range--for example, 90 yards for 3rd-level priests, 100 yards for 4th, 110 yards for 5th, etc. The spell locates such objects as apparel, jewellery, furniture, tools, weapons, or even a ladder or stairway. Once the caster has fixed in his mind the items sought, the spell locates only that item. Attempting to find a specific item, such as a kingdom\'s crown, requires an accurate mental image. If the image is not close enough to the actual item, the spell does not work; in short, desired but unique objects cannot be located by this spell unless they are known by the caster. The spell is blocked by lead.\nThe reversal, obscure object, hides an object from location by spell, crystal ball, or similar means for eight hours. The caster must touch the object being concealed.\nNeither application of the spell affects living creatures.}}{{materials=Jim the Sunblade}}'},
+ {name:'Jims-Sunlight',type:'ItemPower',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} swings\nJim the Sun Blade\nto create Sunlight}}{{splevel=Power}}{{school=Alteration}}Specs=[Jims-Sunlight,ItemPower,1H,Alteration]{{components=S}}{{time=[[3]]}}{{range=[[0]]}}{{duration=While swung}}{{aoe=[Up to 120ft diameter](!rounds --aoe @{selected|token_id}|circle|feet|0|||light|true)}}{{save=None}}{{healing=[Light-em-up!](!rounds --target caster|@{selected|token_id}|SunBlade-Daylight|1|1|Spreading daylight +5ft radius/round to 60ft|aura)}}SpellData=[w:Jims Sunlight,sp:3,cs:VS]{{effects=Once a day, upon command, the blade can be swung vigorously above the head, and it will shed a bright yellow radiance that is like full daylight. The radiance begins shining in a 10-foot radius around the sword-wielder, spreading outward at 5 feet per round for 10 rounds thereafter, creating a globe of light with a 60-foot radius. When the swinging stops, the radiance fades to a dim glow that persists for another turn before disappearing entirely. }}'},
+ {name:'Keraptis-Soul-Trap',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nKeraptis\' Soul Trap\nas a level @{selected|casting-level} caster}}{{splevel=Level 9 Wizard}}{{school=Necromancy}}{{components=V,S,M}}{{time=2+2d8 days}}{{range=Touch}}{{duration=Permanent}}{{aoe=Creatures/Objects touched}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20-4 save vs. Soul Trap death magic)}}{{effects=The ritual that created *Happy the Dummy* from the souls of a LG Magic User and a CE Witchwood Alter - the details of this ritual will help to indicate what has to be done to remove the curse of the dummy, and to release the souls contained.\nThe ritual is similar to a combination of the 6th level Wizard spell *Enchant an Item*, and the 8th level Wizard spells *Maze*,*Trap the Soul* and *Permanency* all used together}}'},
+ {name:'Know-Underwater-Depth',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Determine Approximate Depth Underwater}}{{splevel=Power}}{{school=Divination}}Specs=[Know-Underwater-Depth,Power,0H,Divination]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=While concentrating}}{{aoe=Special}}{{save=None}}SpellData=[w:Know Underwater Depth,sp:0]{{desc=The wielder of this power is often able to determine their approximate depth underwater. They have a 66% chance of being approximately correct, and a 5% chance of being massively wrong (determined by the DM). Other values mean that the wielder can\'t determine the depth.}}'},
+ {name:'Lava-Mephit-Blob',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Lava Mephit breathes out a Blob of Lava}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Lava Mephit Blob,Power,0H,Breath Weapon]{{components=None}}{{time=[[0]]}}{{range=[10 ft](!rounds --aoe @{selected|token_id}|circle|feet|0|20|0|fire|true)}}{{duration=Instantaneous}}{{aoe=1 creature - automatic hit}}{{save=None}}{{damage=Automatic hit [1d6](!\\amp#13;\\amp#47;gmroll 1d6 heat damage, no saving throw) once every [3 rounds](!rounds --target caster|@{selected|token_id}|Timer|2|-1|Counting down until next Lava Blob|stopwatch)}}SpellData=[w:Lava Mephit Blob,sp:0,cs:None,pd:8]{{effects=A molten blob of lava usable once every three melee rounds. This blob automatically hits one target within 10 feet of the breathing mephit (ld6 points of damage, no saving throw). A lava mephit may use this weapon a maximum of eight times, after that, the mephit must recharge by soaking in a lava pool for on hour.}}{{Use=Check the range using the Range button, then do the appropriate damage using the dice roll damage button, and then set a timer to count down for the next blob using the [3 rounds] button}}'},
+ {name:'Lay-On-Harmful-Hands',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nLay on Hands of Harm\nas a Power}}{{splevel=Power}}{{school=Healing}}Specs=[Lay-on-Harmful-Hands,Power,1H,Necromantic]{{components=S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=[[1]] creature}}{{save=Half Damage}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Lay on Harmful Hands,sp:10,cs:S]{{effects=Harm by laying on hands. Inflicts [[2*@{selected|level-class1}]] hit points, half this if the victim saves. Can only be used once per day.}}'},
+ {name:'Lay-On-Healing-Hands',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nLay on Hands of Healing\nas a Power}}{{splevel=Power}}{{school=Healing}}Specs=[Lay-on-Healing-Hands,Power,1H,Necromantic]{{components=S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=[[1]] creature}}{{save=None}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Lay on Healing Hands,sp:10,cs:S]{{effects=Heal by laying on hands. Restores [[2*@{selected|level-class1}]] hit points. They can heal themselves or someone else, but only once per day.}}'},
+ {name:'Leadership',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Leadership}}{{splevel=Power}}{{school=Alteration}}Specs=[Leadership,Power,0H,Alteration]{{components=V}}{{time=[[0]]}}{{range=[30 foot](!rounds --aoe @{selected|token_id}|circle|feet|0|60||light|true)}}{{duration=[[1]] turn}}{{aoe=[[1]] creature or object}}{{save=None}}{{healing=Shout a [Warning](!rounds --target caster|@{selected|token_id}|Leadership|10|-1|Leading, can command ally to add d4 to to-hit or save rolls|fist)}}SpellData=[w:Leadership,sp:0,cs:V]{{desc=For the duration, @{selected|token_name} can shout warnings to any nonhostile creature that it can see within [[30]]ft. of it that makes an attack roll or a saving throw. The creature can add a d4 to its roll provided it can hear and understand the knight. A creature can benefit from only one Leadership die at a time. This effect ends if the knight is incapacitated.}}'},
+ {name:'Lich-Fear',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Fear of the Lich}}{{splevel=Innate Ability}}{{school=Necromancy}}Specs=[Lich-Fear,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Line of Sight, no limit}}{{duration=Fleeing for [5d4 rounds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who sees the Lich?|token_id}|Lich Fear|\\amp#91;[5d4]\\amp#93;|-1|Fleeing at maximum move away from the Lich!|screaming)}}{{aoe=Line of Sight}}{{save=Negates}}SpellData=[w:Lich Fear,sp:0,pd:-1]{{effects=The mere sight of a Lich at any distance causes any creature with less than 5HD to save vs. spell or flee in panic for 2-20 (5d4) rounds unless a saving throw versus spell is made.}}{{Use=Select the Duration button then select each character that fails to save, using the button that appears in the chat window to prompt for you to select each in turn.}}'},
+ {name:'Lightning-Stroke',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Lightning Stroke}}{{splevel=Power}}{{school=Alteration}}Specs=[Lightning Stroke,Power,0H,Alteration]{{components=V,M}}{{time=[[2]]}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=[Lightning Bolt](!rounds --aoe @{selected|token_id}|bolt|feet|0|80|5|lightning)\nor [Lightning Fork](!rounds --aoe @{selected|token_id}|bolt|feet|0|40|10|lightning)\nall creatures within area}}{{save=vs. Staves, for half damage)}}{{damage=[Roll 8d6, 1s as 2s](!\\amp#13;\\amp#47;gr \\amp#91;[{ 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1]\\amp#93;HP damage)}}SpellData=[w:Lightning Stroke,sp:2,cs:VM]{{effects=A bolt similar to that from a wand of lightning is generated, but it is of 8d6 strength, causing 16-48 points of damage (rolls of 1 are counted as 2) to those who fail a saving throw. The stroke can be single or forked.}}'},
+ {name:'Mist-Mephit-Mist-Ball',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Mist Mephit breathes out \nPutrid Gas Ball}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Mist Mephit Ball,Power,0H,Breath Weapon]{{components=None}}{{time=1 every 2 rounds}}{{range=[10 ft](!rounds --aoe @{selected|token_id}|circle|feet|0|20|0|acid|true --target caster|@{selected|token_id}|timer|1|-1|Counting down until Mist Ball can be breathed again|stopwatch)}}{{duration=Instantaneous}}{{aoe=1 creature}}{{save=vs. poison negates}}{{damage=Automatic hit [1d4+1](!\\amp#13;\\amp#47;gmroll 1d4+1 choking damage, save negates)HP, and [blinded](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the victim?|token_id}|blindness|\\amp#91;[1d4]\\amp#93;|-1|Blinded by poison gas, -4 penalty to AC and Attack|bleeding-eye) for 1d4 rounds}}SpellData=[w:Mist Mephit Ball,sp:0,cs:None,pd:3]{{effects=A sickly, green ball of mist, every other round, up to three times an hour. This ball automatically envelopes one victim within 10 feet of the breathing mephit. The victim must roll a successful saving throw vs. poison or suffer 1d4+1 points of choking damage and be blinded for 1d4 rounds.}}{{Use=Display the area of effect using the Range button (also sets timer to count down 1 round to next breath available). Once a victim has failed a save vs. poison, roll damage using the dice roll button, and add the blinding effect using the blinded button and selecting the victim\'s token}}'},
+ {name:'Move-Silently',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nMove Silently\nas a level @{selected|level-class4} @{selected|class4}}}{{splevel=Skill}}{{school=Thieving}}Specs=[Move-Silently,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Self}}{{duration=Until attack}}{{aoe=The character}}{{save=None}}{{healing=[Move Silently](!rounds --target caster|@{selected|token_id}|Move-Silently|99|0|Moving Silently, DM determines success, chance @{selected|mst}pct.|ninja-mask)}}SpellData=[w:Move Silently,sp:0,cs:S]{{effects=The character attempts to move totally silently so as not to attract attention. This may or may not be successful, and depends on their skill. The DM determines success or otherwise but does not tell the player until it becomes relevant to the character.}}'},
+ {name:'Mummy-fear',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Fear of the Mummy}}{{splevel=Innate Ability}}{{school=Necromancy}}Specs=[Mummy-Fear,Power,1H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Line of Sight}}{{duration=1d4 rounds}}{{aoe=Line of Sight}}{{save=[Negates](!\\amp#13;\\amp#47;r 1d4 rounds paralysed with fear)}}{{damage=[Paralyse with Fear](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first to haunt|token_id}|Mummy-fear|\\amp#91;[1d4]\\amp#93;|-1|Petrified! Oh Mummy!|screaming)}}SpellData=[w:Mummy Fear,sp:0,cs:S]{{effects=The mere sight of a mummy causes such terror in any creature that a saving throw versus spell must be made or the victim becomes paralyzed with fright for 1 to 4 rounds. Numbers will bolster courage; for each six creatures present, the saving throw is improved by +1. Humans save against mummies at an additional +2.}}'},
+ {name:'NWP-Healing',type:'Power',ct:'60',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} performs\nNWP Healing}}{{splevel=Non-Weapon Proficiency}}{{school=Healing}}Specs=[NWP-Healing,Power,1H,Necromancy]{{components=V,S}}{{time=[[60]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=Up to [[6]] creatures}}{{save=None}}{{healing=Select type below. Only 1 healing attempt per character per day}}SpellData=[w:NWP Healing,sp:60,cs:VS]{{effects=[1st Aid](!setattr --silent --charid @{selected|character_id} --spell-cast|Do-1st-aid\\amp#13;!token-mod --ignore-selected --ids \\amp#64;{target|Tend to which creature?|token_id} --set bar3_value|+\\amp#91;[\\amp#63;{How much First Aid?|1d3}]\\amp#93;! --report control|{name} is healed from {bar3_value:change}HP\\amp#13;!magic --cast-again power|@{selected|token_id}|Do-1st-aid):Tending within 1 round of wounding (needs **proficiency check**) restores 1d3 HP (limited to loss in previous round).\nFor daily care no proficiency check is needed. Up to 6 patients, once/day:\n[Day care 1HP](!setattr --silent --charid @{selected|character_id} --spell-cast|Do-day-care\\amp#13;!token-mod --ignore-selected --ids \\amp#64;{target|Tend to which creature?|token_id} --set bar3_value|+1! --report control|{name} is healed by 1 from {bar3_value:change}HP\\amp#13;!magic --cast-again power|@{selected|token_id}|Do-1HP-care):Recover 1 HP/day during nonstrenuous activity.\n[Overnight Care 2HP](!setattr --silent --charid @{selected|character_id} --spell-cast|Do-2HP-care\\amp#13;!token-mod --ignore-selected --ids \\amp#64;{target|Tend to which creature?|token_id} --set bar3_value|+2! --report control|{name} is healed by 2 from {bar3_value:change}HP\\amp#13;!magic --cast-again power|@{selected|token_id}|Do-2HP-care):Complete rest overnight can recover 2 HP overnight.\n*[NWP Healing + Herbalism 3HP](!setattr --silent --charid @{selected|character_id} --spell-cast|Do-3HP-care\\amp#13;!token-mod --ignore-selected --ids \\amp#64;{target|Tend to which creature?|token_id} --set bar3_value|+3! --report control|{name} is healed by 3 from {bar3_value:change}HP\\amp#13;!magic --cast-again power|@{selected|token_id}|Do-3HP-care)*: gives 3 HP overnight.\n**Poison:** Aid if poison entered through a wound. Tending within 1 round of poisoning and continuing for 5 rounds, victim gains +2 bonus to saves (delay throw until last round of tending). No proficiency check required **if sacrificing any other action** by either character. If interrupted, poisoned character must roll normal saving throw for the poison: more healing doesn\'t help. Both *healing + herbalism* required to treat poisons swallowed or touched.\n**Disease:** Can attempt to diagnose and treat diseases. For normal diseases, successful **proficiency check** automatically reduces disease to mildest form and shortest duration. If also have *herbalism* gain an additional +[[2]] bonus to check. Can also attempt to diagnose magical diseases: successful **proficiency check** diagnoses the cause. As disease is magical, can be treated only by magical means.}}\n!setattr --silent --name @{selected|character_name} --power-exhausted|I\'m afraid you have tended to the maximum 6 creatures today. You deserve a rest!'},
+ {name:'Oni-Cone-of-Cold',type:'Power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} casts\nCone of Cold\nas an Oni}}{{splevel=Power}}{{school=Evocation}}Specs=[Oni-Cone-of-Cold,Power,1H,Evocation]{{components=V, S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=[60ft cone, 20ft dia. base](!rounds --aoe @{selected|token_id}|cone|feet|0|60|20|cold|true)}}{{save=[Half](!\\amp#13;\\amp#47;gmroll 1d20 save vs. Cone of Cold spell)}}{{damage=[8d8](!\\amp#13;\\amp#47;gmroll 8d8 HP damage, save to half)}}SpellData=[w:Oni Cone of Cold,sp:5,cs:VS]{{effects=When this spell is cast, it causes a cone-shaped area of extreme cold, originating at the wizard\'s hand and extending outward in a cone 60 feet long and 20 foot in diameter at its base. It drains heat and causes 8d8 points of damage}}{{material=A crystal or glass cone of very small size.}}'},
+ {name:'Paladin-Detect-Evil',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nDetect Evil Intent\nas a level @{selected|level-class1} @{selected|class1}}}{{splevel=Power}}{{school=Divination}}Specs=[Paladin-Detect-Evil,Power,1H,Divination]{{components=S}}{{time=[[10]]}}{{range=0}}{{duration=[[1]] round}}{{aoe=[60ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|120||magic|true)}}{{save=None}}{{reference=PHB p27}}SpellData=[w:Paladin Detect Evil,sp:10,cs:S]{{effects=A paladin can detect the presence of evil intent up to 60 feet away by concentrating on locating evil in a particular direction. He can do this as often as desired, but each attempt takes one round. This ability detects evil monsters and characters.}}'},
+ {name:'Paladin-lay-on-hands',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nLay on Hands\nas a level @{selected|level-class1} @{selected|class1}}}{{splevel=Power}}{{school=Healing}}Specs=[Paladin-lay-on-Hands,Power,1H,Necromantic]{{components=S}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=[[1]] creature}}{{save=None}}{{reference=PHB p27}}SpellData=[w:Paladin Lay on Hands,sp:10,cs:S]{{effects=A paladin can heal by laying on hands. The paladin restores [[2*@{selected|level-class1}]] hit points. They can heal themselves or someone else, but only once per day.}}'},
+ {name:'Paralyse',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nParalyse\nas a level @{selected|casting-level} caster}}{{splevel=Monster ability}}{{school=Alteration}}Specs=[Paralyse,Power,1H,Alteration]{{components=S}}{{time=[[2]]}}{{range=Touch}}{{duration=1d4 rounds}}{{aoe=varies}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw)}}{{damage=[Paralyse](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select future statues|token_id}|Paralyse|\\amp#91;[\\amp#63;{Duration?|1d4}]\\amp#93;|-1|Paralysed|fishing-net) }}SpellData=[w:Paralyse,sp:2,cs:S]{{effects=A paralysation effect is often caused by monsters attacking the party, and is similar in effect to a \'Hold\' spell}}'},
+ {name:'Petrification-Gaze-Attack',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses a\nPetrification Gaze Attack}}{{splevel=Power}}{{school=Alteration}}Specs=[Petrification Gaze,Power,1H,Alteration]{{components=None}}{{time=[[0]]}}{{range=0}}{{duration=[Permanent](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who is the unfortunate soul?|token_id}|Petrified|99|0|Petrified by a Gaze Attack|padlock)}}{{aoe=When meet gaze, e.g. surprised, if doing attack etc}}{{save=vs. Petrification Negates}}{{reference=DMG p64}}SpellData=[w:Petrification Gaze,sp:0,pd:-1]{{effects=Monsters with a gaze attack, such as the basilisk, have the power to affect an opponent simply by making eye contact. This makes these creatures incredibly dangerous, for the slightest glance can cause great harm.\nCharacters who look directly at such creatures to attack them, or those who are surprised by the creature, automatically meet the creature\'s gaze. These unfortunate characters must make the appropriate saving throw or suffer the effects of the creature\'s attack. Such attackers undergo the gaze attack each round they attack. In large groups, only the front rank can meet the gaze, a fate that can be avoided if the attacker\napproaches from the rear, where the creature cannot see.\nCharacters can also attempt to avoid the gaze by looking in the general direction of the creature without actually looking into its eyes. This enables characters to see the target well enough to fight normally without falling victim to its power. However, there is a 20% chance each round that an attacker trying this trick will accidentally meet the gaze of the creature.\nFinally, a character can completely avert his gaze or close his eyes when attacking the creature, preventing any chance of meeting the creature\'s gaze. This is like fighting in the dark, and the character suffers all the normal penalties for fighting while blinded.}}'},
+ {name:'Prestidigitation',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Prestidigitation}}{{splevel=Cantrip}}{{school=Alteration}}Specs=[Prestidigitation,Power,1H,Alteration]{{components=V,S}}{{time=[[0]]}}{{range=[[10]] feet}}{{duration=Up to [[1]] hour}}{{aoe=Special}}{{save=None}}SpellData=[w:Prestidigitation,sp:0,cs:VS]{{effects=This spell is a minor magical trick that novice spellcasters use for practice. You create one of the following magical effects within range: You create an instantaneous, harmless sensory effect, such as a shower of sparks, a puff of wind, faint musical notes, or an odd odour. You instantaneously light or snuff out a candle, a torch, or a small campfire. You instantaneously clean or soil an object no larger than 1 cubic foot. You chill, warm, or flavour up to 1 cubic foot of non-living material for 1 hour. You make a colour, a small mark, or a symbol appear on an object or a surface for 1 hour. You create a nonmagical trinket or an illusory image that can fit in your hand and that lasts until the end of your next turn. If you cast this spell multiple times, you can have up to three of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action.}}'},
+ {name:'Prophesy',type:'Power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to make a\nProphesy\nusing a Power}}{{splevel=Class Ability}}{{school=Divination}}Specs=[Prophesy,Power,1H,Divination]{{components=None}}{{time=[10 turns meditating](!rounds --target caster|@{selected|token_id}|Prophesy|100|-1|Meditating - do not disturb|stopwatch) *(click to start)*}}{{range=0}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{Reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Prophesy,sp:1,cs:None]{{effects=With this power, the priest can sometimes see visions of the future. The priest sinks into a meditative trance and try to receive visions of the future. This trance lasts ten turns; if the priest is interrupted before the ten turns are done (struck with a weapon, shouted at by someone within six feet of him, or knocked over), the trance is prematurely broken and the priest gets no vision.\nIt is sometimes possible for the priest to receive visions without trying - their god may foist one on them.}}'},
+ {name:'Purify-Water',type:'Power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} has\nPurify Water\nas a Power cast at @{selected|Casting-Level} level}}{{splevel=Power}}{{school=Alteration}}Specs=[Purify-Water,Power,1H,Alteration]{{components=None}}{{time=[[5]]}}{{range=30 yds}}{{duration=Permanent}}{{aoe=[@{selected|casting-level} cu. ft.](!rounds --aoe @{selected|token_id}|rectangle|feet|90|||blue)}}{{save=None}}SpellData=[w:Purify-Water,lv:1,sp:5,gp:0]{{effects=Makes spoiled, rotten, poisonous, or otherwise contaminated water pure and suitable for drinking. Up to 1 cubic foot of water per level can be thus made suitable for consumption. This spell does not prevent subsequent natural decay or spoilage. Unholy water is spoiled by purify water, but the power has no effect on creatures of any type nor upon magical potions.}}'},
+ {name:'Quasit-Fear',type:'Power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses their\nFear power}}{{splevel=Quasit power}}{{school=Illusion/Phantasm}}Specs=[Quasit-Fear,Power,0H,Illusion-Phantasm]{{components=None}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[[3]] rounds}}{{aoe=[30ft. radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60||acid|true)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 saving throw vs. Fear spell)}}{{damage=[Frighten them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first target|token_id}|Fear|3|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming)}}SpellData=[w:Quasit Fear,sp:4,cs:None]{{effects=Sends forth invisible circle of terror. Creatures within area of effect turn away from the caster and flee. Affected creatures are likely to drop whatever they are holding; base chance is [[60]]% at 1st level/1HD, each level/HD above reduces probability by [[5]]%. Creatures affected flee at fastest rate for 3 rounds. Undead and successful saves vs. spell are not affected.}}'},
+ {name:'Rage',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} starts\nRaging\nas a level @{selected|level-class1} Barbarian}}{{splevel=Power}}{{school=Barbarian}}Specs=[Rage,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Self}}{{duration=[[10]] Rounds Rage, then [[10]] Rounds recovery}}{{aoe=Self}}{{save=None}}{{healing=[Rage!](!rounds --target caster|@{selected|token_id}|Rage|10|-1|RAGE +2 bonus on att+dam+AC|overdrive)}}SpellData=[w:Rage,sp:0,cs:S]{{effects=This Barbarian may "Rage" [[{ceil(@{selected|level-class1}/4),3}kl1]] times a day for [[10]] melee rounds. When raging his AC, Thac0 and Damage all improve by [[2]]. When raging he gains [[15]] temporary hit points. After the 10 melee rounds he loses those. If that would take him below zero, he falls unconscious. He does not attack team-mates when raging but does not accept surrender from enemies. After raging if still conscious he is winded and his THAC0 AC and Damage decrease by [[0-2]] for [[10]] rounds. While Raging he is immune to *Sleep, Charm, Fear, Confusion, Level Drain, Maze, Stun, Imprisonment, Feeblemind* and *Hold* spells.\nIf desired, to end Rage early after melee use "View Powers" to view "Rage", then use\n[End Current Rage](!rounds --removetargetstatus @{selected|token_id}|Rage) or\n[End Exhaustion](!rounds --removetargetstatus @{selected|token_id}|Exhausted)}}'},
+ {name:'Rangers-Animal-Friendship',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to use\nRanger\'s Animal Friendship\nas a Power}}{{splevel=Class Ability}}{{school=Enchantment-Charm}}Specs=[Rangers-Animal-Friendship,Power,1H,Enchantment-Charm]{{components=None}}{{time=[[10]]}}{{range=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|20||magic|true)}}{{duration=Special}}{{aoe=Special}}{{save=Negates. Save vs Rod at a [[0-ceil(@{selected|casting-level}/3)]] penalty}}{{Reference=PHB p29}}SpellData=[w:Rangers-Animal-Friendship,sp:10,cs:None]{{effects=Rangers are adept with both trained and untamed creatures, having a limited degree of animal empathy. If a ranger carefully approaches or tends any natural animal, he can try to modify the animal\'s reactions. (A natural animal is one that can be found in the real world -- a bear, snake, zebra, etc.)\nDomestic or non-hostile animals can be approached and befriended automatically.\nWild and attack-trained animals roll a saving throw vs. rods with a -1 penalty per three levels of the Ranger. If failed, the creature\'s reaction can be shifted one category as the ranger\nchooses.}}'},
+ {name:'Regenerate',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} Regenerates HP}}{{splevel=Innate Power}}{{school=Necromancy}}Specs=[Regenerate,Power,0H,Necromancy]{{components=S}}{{time=[[0]] and in parallel with other activity}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=The creature}}{{save=None)}}{{healing=[Regenerates @{selected|conregen}HP](!modbattr --fb-header Regenerating --fb-content @{selected|token_name} regenerates _TCUR0_ HP and now has _CUR0_ HP --charid @{selected|character_id} --hp|@{selected|conregen}) or [Regen every round](!rounds --target caster|@{selected|token_id}|Regeneration|99|0|Regenerating at @{selected|conregen}HP per round|strong)}}SpellData=[w:Regenerate,sp:0,cs:S]{{effects=This creature can regenerate damage up to their maximum HP at the rate of [[@{selected|conregen}]] per use of the Power}}'},
+ {name:'Resurrection-Rod',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.wandTemplate+'}{{title=Rod of Resurrection}}{{subtitle=Rod}}Specs=[Rod of Resurrection,Power,1H,Necromancy]{{components=V,M}}{{time=1 turn}}SpellData=[w:Rod of Resurrection,sp:10,cs:VM]{{range=Touch}}{{desc=This rod enables a cleric to [resurrect the dead](!magic --mi-charges @{selected|token_id}|-\\amp#63;{What Race?|Dwarf,3|Elf,4|Gnome,3|Half-elf,2|Halfling,2|Human,1}-\\amp#63;{What Class?|Cleric,1|Druid,2|Fighter,2|Paladin,1|Ranger,2|Mage,3|Illusionist,3|Thief,3|Bard,2}|Rod of Resurrection|||There are enough charges to attempt this resurrection, and these have been expended. Now roll for Resurrection Survival.) - even elven, dwarven, gnome, or halfling - as if he were of high enough level to cast the resurrection spell. No rest is required, as the rod bestows the life giving effects.\nThe rod can be used once per day. The number of charges used to resurrect a character depends on class and race. Total the number of charges indicated for the character\'s class\nand race:\n\\amplt;table\\ampgt;\\amplt;thead\\ampgt;\\amplt;th scope="col"\\ampgt;Class\\amplt;/th\\ampgt;\\amplt;th scope="col"\\ampgt;Charges\\amplt;/th\\ampgt;\\amplt;th scope="col"\\ampgt;Race\\amplt;/th\\ampgt;\\amplt;th scope="col"\\ampgt;Charges\\amplt;/th\\ampgt;\\amplt;/thead\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Cleric\\amplt;/td\\ampgt;\\amplt;td\\ampgt;1\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Dwarf\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Druid\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Elf\\amplt;/td\\ampgt;\\amplt;td\\ampgt;4\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Fighter\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Gnome\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Paladin\\amplt;/td\\ampgt;\\amplt;td\\ampgt;1\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Half-elf\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Ranger\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Halfling\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Mage\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Human\\amplt;/td\\ampgt;\\amplt;td\\ampgt;1\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Illusionist\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Thief\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Bard\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;/th\\ampgt;\\amplt;/table\\ampgt;\nMulti-classed characters use the least favorable category. The rod cannot be recharged.}}{{Use=Now, use the [resurrect the dead] button to attempt the resurection}}'},
+ {name:'Rite-of-Arcs-Dilemma',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nThe Rite of Arc\'s Dilemma\nas a level @{selected|casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}{{components=V, S}}{{time=[[1]] day per level transferred}}{{range=[[0]]}}{{duration=Permanent}}{{aoe=Caster}}{{save=None}}{{effects=A ritual that will allow reassignment of experience between classes. The subject of the casting must undertake the ritual for 1 hour each day for as many days as levels to be gained. Each day, the subject must roll percentile dice to see if the rite has been performed correctly, the chance of it working being 70% + the subject\'s Intelligence score (max 90%). If the check fails, no more performances of the rite at this level will work, and as per the specification of the Tome the avatar of Math Mathonwy may appear and attempt to reclaim the Tome (20% + 5% chance per level successfully being reassigned, max 90% chance - see AD\\ampD Legends \\amp Lore - Celtic Mythos for details of the avatar). Another attempt can be made as the subject gains levels of experience in the normal way.\nThe subject loses 1 level per day from the original class and gains 1 level per day in the new class up to the number transferred - this does not include any necessary training: the subject will need to locate and organise their own training in the necessary skills. \nThe DM may rule that action may need to be taken to pay penance for the loss of the class whose levels have been reduced: a Priest may need to *atone* to their (ex-) god or priesthood, a Rogue pay reparations to their guild for the lost talent and income, etc.}}'},
+ {name:'Ritual-of-the-New-Moon',type:'Power',ct:'1200',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nRitual of the New Moon}}{{splevel=Power}}{{school=Necromancy}}{{sphere=Necromancy}}Specs=[Ritual-of-the-New-Moon,Power,1H,Necromancy]{{components=V,S}}{{time=[[2]] hours}}{{range=[[0]]}}{{duration=[Special](!rounds --target caster|@{selected|token_id}|Ritual of the New Moon|99|0|Increased in levels until 24 hours after the New Moon|aura)}}{{aoe=Special}}{{save=None}}{{reference=House Rules p20}}SpellData=[w:Ritual of the New Moon,sp:1200,cs:VS,sph:Necromancy]{{effects=Makes a living sacrifice of at least a 2HD creature in the 48 hours centred on the new moon (captured, with ceremonies, not in battle), subsequently casts spells as if 1 level higher until the 48 hours around the full moon have ended; similarly, casts spells as if 2 levels higher for the 48 hours centred on the Spring and Autumn Equinox but only if sacrificing a 4HD creature; and casts spells as if 3 levels higher for the 48 hours centred on the Winter and Summer Solstice, but only if sacrificing a 6HD creature. This includes gaining the appropriate higher-level spells for that period}}'},
+ {name:'RoE-Clairaudience',type:'ItemPower',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|mu-casting-name} casts\nClairaudience\nas a level @{selected|mu-casting-level} caster}}{{splevel=Power}}{{school=Divination}}Specs=[RoE-Clairaudience,ItemPower,0H,Divination]{{components=V}}{{time=[[3]]}}{{range=Unlimited}}{{duration=[[@{selected|mu-casting-level}]] rounds}}{{aoe=[[60]]ft radius of selected spot}}{{save=None}}{{healing=[Super-Hearing](!rounds --target caster|@{selected|token_id}|Clairaudience|[[@{selected|mu-casting-level}]]|-1|Normal hearing but at a distance|Strong)}}SpellData=[w:RoE-Clairaudiece,sp:3,cs:VSM]{{effects=The clairaudience spell enables the wizard to concentrate upon some locale and hear in his mind any noise within a 60-foot radius of that point. Distance is not a factor, but the locale must be known--a place familiar to the spellcaster or an obvious one (such as behind a door, around a corner, in a copse of trees, etc.). Only sounds that are normally detectable by the wizard can be heard by use of this spell. Lead sheeting or magical protections prevent the operation of the spell, and the wizard has some indication that the spell is so blocked. The spell creates an invisible sensor, similar to that created by a crystal ball spell, that can be dispelled. The spell functions only on the wizard\'s current plane of existence}}{{materials=A small horn of at least 100 gp value.}}'},
+ {name:'RoSS-Ball-Lightning',type:'ItemPower',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Ring of Spell Storing casts\nBall Lightning}}{{school=Evocation}}Specs=[RoSS-Ball-Lightning,ItemPower,1H,Evocation]{{splevel=Power}}{{components= S}}{{time=[[5]]}}{{range=[[120]]ft.}}{{duration=[[4]]rounds}}{{aoe=[Create a Ball](!rounds --aoe @{selected|token_id}|circle|feet|120|3||lightning)}}{{save=[Half damage](!\\amp#13;\\amp#47;gmroll 1d20 saving throw vs. spell)}}{{damage=Select number of balls below}}{{damagetype=Lightning}}SpellData=[w:RoSS-Ball-Lightning,sp:5,cs:SM]{{effects=The *ball lightning* function releases 1d4 balls of lightning, at the wearer\'s option. These glowing globes resemble dancing lights, and the ring wearer controls them as he would control dancing lights. These spheres have a 120-foot range and a four round duration. They can be moved at 120 feet per round. Each sphere is about 3 feet in diameter, and any creature it touches or approaches within 5 feet dissipates its charge (a successful save vs. spell halves damage—the contact was across an air gap). The charge damage values are:\n[4 lightning balls](!\\amp#13;\\amp#47;r 2d4 HP damage from ball lightning).........2d4 HP each\n[3 lightning balls](!\\amp#13;\\amp#47;r 2d6 HP damage from ball lightning).........2d6 HP each\n[2 lightning balls](!\\amp#13;\\amp#47;r 5d4 HP damage from ball lightning).........5d4 HP each\n[1 lightning ball](!\\amp#13;\\amp#47;r 4d12 HP damage from ball lightning)...........4d12 HP\nRelease can be one at a time or all at once, during the course of one round or as needed throughout the night.}}'},
+ {name:'RoSS-Shooting-Stars',type:'ItemPower',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} casts\nShooting Stars\nusing a Ring of Shooting Stars}}{{school=Evocation}}{{splevel=Power}}Specs=[RoSS-Shooting-Stars,ItemPower,1H,Evocation]{{components=S}}{{time=[[5]]}}{{range=[70 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|140||light|true)}}{{duration=Special}}{{aoe=Special}}{{save=[Special](!\\amp#13;\\amp#47;gmroll 1d20 saving throw vs. spell)}}{{damage=Creature Hit takes 12+24 HP in total (no save).\nCreatures within 5ft radius take 24HP (save to half)}}{{damagetype=Fire}}SpellData=[w:RoSS Shooting Stars,sp:5,cs:S]{{effects=The *shooting stars* are glowing missiles with fiery trails, much like a meteor swarm. Three shooting stars can be released from the ring each week, simultaneously or one at a time. They impact for 12 points of damage (save vs. spell to avoid) and burst (as a fireball) in a 10-foot diameter sphere for 24 points of damage (save to half).\nAny creature struck (failed avoiding save) takes full damage from impact plus full damage from the shooting star burst. Creatures within the burst radius must roll a saving throw vs. spell to take only one-half damage (i.e., 12 points of damage, otherwise they, too, receive the full 24 points of damage). Range is 70 feet, at the end of which the burst will occur, unless an object or creature is struck before that. The shooting stars follow a straight line path. A creature in the path must roll a saving throw vs. spell or be hit by the missile. **Saving throws suffer a [[0-3]] penalty** within 20 feet of the ring wearer, [[0-1]] from 21 feet to 40 feet, normal beyond 40 feet.}}'},
+ {name:'RoSS-Spark-Shower',type:'ItemPower',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} casts\nShooting Stars\nfrom a Ring of Shooting Stars}}{{school=Evocation}}{{splevel=Power}}Specs=[RoSS-Spark-Shower,ItemPower,1H,Evocation]{{components=S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[Cone 20ft long, 10ft at end](!rounds --aoe @{selected|token_id}|cone|feet|0|20|10|light|true)}}{{save=None)}}{{damage=Metal worn/held [4d4](!\\amp#13;\\amp#47;r 4d4 HP from sparks), otherwise [2d8](!\\amp#13;\\amp#47;r 2d8 HP from sparks) HP from sparks}}{{damagetype=Electrical}}SpellData=[w:RoSS Spark Shower,sp:5,cs:S]{{effects=The *spark shower* is a flying cloud of sizzling purple sparks, which fan out from the ring for a distance of 20 feet to a breadth of 10 feet. Creatures within this area take 2d8 points of damage each if no metal armor is worn and/or no metal weapon is held. Characters wearing metal armor or carrying a metal weapon receive 4d4 points of damage.}}'},
+ {name:'Serpentine-Giant-Owl',type:'Power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nFigurine of the Serpentine Owl\n(Giant Owl)}}{{splevel=Magic Item}}{{school=Conjuration/Summoning}}Specs=[Serpentine Giant Owl,Power,1H,Conjuration-Summoning]{{components=V,M}}{{time=[[3]]}}{{range=[[0]]}}{{duration=8 hours}}{{aoe=Figurine}}{{save=None}}SpellData=[w:Serpentine Giant Owl,sp:3,cs:VM]{{effects=Speaking the command work transforms the *Figurine of the Serpentine Owl* (a *Figurine of Wonderous Power*) into a *Giant Owl*. Ask the GM to *Drag \\amp Drop* a *Giant Owl* onto the map from the *Creature Database*. Note that this can only be done 3 times before the figurine loses all magical properties}}'},
+ {name:'Shapechange',type:'Power',ct:'9',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nShape Change\nas a Power}}{{splevel=Power}}{{school=Alteration}}Specs=[Shapechange,Power,1H,Alteration]{{components=V,S}}{{time=[[9]]}}{{range=[[0]]}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Shapechange-Power|[[10*@{selected|casting-level}]]|-1|Masqurading as a different natural creature|aura)}}{{aoe=The caster}}{{save=None}}{{reference=PHB p37}}SpellData=[w:Shapechange,sp:9,cs:VS]{{effects=A druid (or other priest) gains the ability to shapechange into a reptile, bird, or mammal up to three times per day after he reaches 7th level. Each animal form (reptile, bird, or mammal) can be used only once per day. The size can vary from that of a bullfrog or small bird to as large as a black bear. Upon assuming a new form, the druid heals 10-60% (1d6 _ 10%) of all damage he has suffered (round fractions down). The druid can only assume the form of a normal (real world) animal in its normal proportions, but by doing so he takes on all of that creature\'s characteristics -- its movement rate and abilities, its Armor Class, number of attacks, and damage per attack.\nThe druid\'s clothing and one item held in each hand also become part of the new body; these reappear when the druid resumes his normal shape. The items cannot be used while the druid is in animal form.}}'},
+ {name:'Smoke-Mephit-Soot-ball',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Smoke Mephit breathes out \na Sooty Ball}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Smoke Mephit Ball,Power,0H,Breath Weapon]{{components=None}}{{time=1 every 2 rounds}}{{range=[20 ft](!rounds --aoe @{selected|token_id}|circle|feet|0|40|0|acid|true --target caster|@{selected|token_id}|timer|1|-1|Counting down until Soot Ball can be breathed again|stopwatch)}}{{duration=Instantaneous}}{{aoe=1 creature}}{{save=None}}{{damage=Automatic hit [1d4](!\\amp#13;\\amp#47;gmroll 1d4+1 HP damage)HP, and [blinded](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the victim?|token_id}|blindness|\\amp#91;[1d2]\\amp#93;|-1|Blinded by soot, -4 penalty to AC and Attack|bleeding-eye) for 1d2 rounds}}SpellData=[w:Smoke Mephit Ball,sp:0,cs:None,pd:-1]{{effects=A sooty ball usable every other melee round, with no limit on the number of times it can be used in a day. The sooty ball automatically strikes one creature of the mephit\'s choice within 20 feet, causing ld4 points of damage and blinding the victim for 1-2 rounds. No saving throw is permitted.}}{{Use=Display the area of effect using the Range button (also sets timer to count down 1 round to next breath available). Then roll damage using the dice roll button, and add the blinding effect using the blinded button and selecting the victim\'s token}}'},
+ {name:'Snake-Poison-Type-3',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Snake Poison (type 3)}}{{splevel=Innate Ability}}{{school=Poison}}Specs=[Snake-Poison-Type-3,Power,0H,Innate Ability]{{components=S}}{{time=[[0]]}}{{range=Bite}}{{duration=2d6 rounds}}{{aoe=Bitten creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs poison)}}{{damage=[Bite](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who has been poisoned?|token_id}|Snake-Poison-3|\\amp#91;[2d6]\\amp#93;|-1|Poisoned, will damage by 2d4hp if not neutralised|death-zone)}}SpellData=[w:Snake Poison Type 3,sp:0,cs:S]{{effects=All poisonous snakes deliver toxins automatically through their bite. Typical varieties of poisonous snakes include the asp, cobra, copperhead, coral snake, death adder, krait, mamba, puff adder, rattlesnake, sidewinder, and water moccasin.\nThis particular type of poison has a delayed action, causing 2d4 damage after 2d6 rounds if not neutralised.\nSome cobras and sidewinders hunt by night and can track warmblooded prey by body heat as well as by sight. They have the equivalent of 30-foot infravision. Black mambas are the fastest known snakes and can reach 30 across open ground.}}'},
+ {name:'Soothing-Word',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses\nSoothing Word\nas a Power}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Soothing-Word,Power,0H,Enchantment-Charm]{{components=V}}{{time=[[10]]}}{{range=[[0]]}}{{duration=Permanent or as determined by DM)}}{{aoe=[[1]] creature or [[2*@{selected|casting-level}]] creatures}}{{save=Special}}{{reference=*The Complete Priest\'s Handbook*, Powers}}SpellData=[w:Soothing Word,sp:10,cs:V]{{effects=The priest can remove the effects of the fear spell or can sway the attitude of a hostile crowd or mob.\nThe priest can use this power three times per day. A single use can either: Dispel one application of the fear spell on one victim; eliminate one warrior\'s berserker rage; or momentarily calm down a number of characters or monsters (equal to 2x the priest\'s experience level in hit dice; therefore an 8th level priest could momentarily calm 16 HD of angry mob, for instance).\nThis power is primarily useful for getting the attention of an angry group of people and allowing the priest to address them. The combination of the soothing word , the respect that many cultures have for their priests, and the speaking abilities of many priests can often defuse an angry mob.}}'},
+ {name:'Spectator-Cause-Serious-Wounds',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Sectator Guardian casts\nCause Serious Wounds}}{{splevel=Spectator Guardian}}{{school=Necromancy}}{{sphere=Healing (Reversed)}}{{components=None}}{{time=[[7]]}}{{range=[[60]] yards}}{{duration=Instantaneous}}{{aoe=1 Creature}}{{save=[Half Damage](!\\amp#13;\\amp#47;gmroll 1d20 Save vs. Spell to take half damage)}}{{damage=[2d8+3](!\\amp#13;\\amp#47;gmroll 2d8+3 HP damage)}}{{effects=Spectator Guardian Beholder-kin uses its 2nd minor eye to cast a special Cause Serious Wounds, which inflicts 2d8+3 points of damage to a single being at a range of 60 yards; a saving throw vs. spell is allowed for half damage}}'},
+ {name:'Spectator-Create-F+W',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Sectator Guardian casts\nCreate Food and Water}}{{splevel=Spectator Guardian}}{{school=Alteration}}{{sphere=Creation}}{{components=None}}{{time=[[1]]round}}{{range=[[10]] yards}}{{duration=Special}}{{aoe=Meal for 6 with water to drink}}{{save=None}}{{effects=Causes food and water to appear. The food thus created is highly nourishing if rather bland, enough for 6 people. The food decays and becomes inedible within 24 hours, although it can be restored for another 24 hours by casting a purify food and water spell upon it. The water created by this spell is the same as that created by the 1st-level priest spell create water.}}'},
+ {name:'Spectator-Paralysation-Ray',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Sectator Guardian casts\nParalyzation Ray}}{{splevel=Spectator Guardian}}{{school=Enchantment/Charm}}{{components=None}}{{time=[[0]] innate attack}}{{range=[[90]] feet}}{{duration=[8d4](!\\amp#13;\\amp#47;gmroll 8d4 rounds of paralysation) rounds}}{{aoe=1 Creature}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs. paralysation)}}{{effects=Spectator Guardian Beholder-kin uses its 3rd minor eye to cast a special Paralysation Ray against 1 creature, causing paralysis for 8d4 rounds. The Spectator will attempt to then telepathically reason with the creature(s) so paralysed to retain it\'s treasure}}'},
+ {name:'Spectator-Spell-Reflection',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Sectator Guardian casts\nSpell Reflection}}{{splevel=Spectator Guardian}}{{school=Abjuration}}{{components=None}}{{time=[[0]] innate power}}{{range=[[0]]}}{{duration=Continuous}}{{aoe=1 Spell per Round}}{{save=[Reflects](!\\amp#13;\\amp#47;gmroll 1d20 save vs. spell success reflects spell)}}{{effects=Spectator Guardian Beholder-kin uses its **undamaged** main eye to *Reflect* [[1]] spell per round. \nThis powerful abjuration causes spells cast against the wizard to rebound on the original caster. This includes spells cast from scrolls and innate spell-like abilities, but specifically excludes the following: area effects that are not centered directly upon the protected wizard, spell effects delivered by touch, and spell effects from devices such as wands, staves, etc. Thus, a light spell cast to blind the protected wizard could be turned back upon and possibly blind the caster, while the same spell would be unaffected if cast to light an area within which the protected wizard is standing.\nIf the protected wizard and a spellcasting attacker both have spell turning effects operating, a resonating field is created that has the following effects:\n\n**D100 Roll Effect**\n**01-70** Spell drains away without effect\n**71-80** Spell affects both equally at full damage\n**81-97** Both turning effects are rendered nonfunctional for [1d4](!\\amp#13;\\amp#47;gmroll 1d4) turns\n**98-00** Both casters go through a rift into the Positive Energy plane}}'},
+ {name:'Spectator-Telepathy',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Sectator Guardian casts\nTelepathy}}{{splevel=Spectator Guardian}}{{school=Divination}}{{components=None}}{{time=[[0]] innate power}}{{range=[[120]] feet}}{{duration=Continuous}}{{aoe=1 Creature}}{{save=[Negates Suggestion](!\\amp#13;\\amp#47;gmroll 1d20 save vs. spell)}}{{effects=Spectator Guardian Beholder-kin uses its 4th minor eye to establish a Telepathic link with 1 creature. It will almost always attempt to immediately use [*Suggestion*](!magic --display-ability @{selected|token_id}|MU-Spells-DB|Suggestion) to implant *"leave in peace"* if the target does not save vs. spell. If the save is made, the Spectator will attempt to telepathically reason with the creature to retain the treasure it is protecting.}}'},
+ {name:'Spit-Poison',type:'Innate-Ranged|Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Spit Poison}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Spit Poison,Innate-Ranged|Power,0H,Spit Poison]{{components=S}}SpellData=[w:Spit Poison,sp:0,cs:S]{{time=0}}ToHitData=[w:Spit Poison,+:0,sb:0,equip:prime,n:1,ch:20,cm:1,sz:T,ty:SPB,sp:0]{{range=30ft, Line of sight}}AmmoData=[w:Snake Poison 1-4,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 1-4_Not quite right\\vbar;\\amp#91;\\lbrak;8+3d10\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar; ],[w:Snake Poison 5-6,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 1-4_Not quite right\\vbar;\\amp#91;\\lbrak;1+1d4\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;],[w:Snake Poison 7-11,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 7-11_Not quite right\\vbar;\\amp#91;\\lbrak;2d6\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;],[w:Snake Poison 12-14,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 12-14_Not quite right\\vbar;\\amp#91;\\lbrak;1d6\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;],[w:Snake Poison 15-17,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 15-17_Not quite right\\vbar;\\amp#91;\\lbrak;2d4\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;],[w:Snake Poison 18-19,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 18-19_Not quite right\\vbar;\\amp#91;\\lbrak;1d4\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;],[w:Snake Poison 20,st:Spit Poison,ru:2,msg:**Don\'t make saving throw now!** First \\lbrak;apply poison\\rbrak;\\lpar;!rounds --target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who is the Unfortunate Victim?\\vbar;token_id}\\vbar;Poison Snake 20_Not quite right\\vbar;\\amp#91;\\lbrak;1\\rbrak;\\amp#93;\\vbar;-1\\vbar;That bite was quite painful. Should I see a Cleric?\\vbar;stopwatch\\rpar;]{{duration=Depends on poison type}}RangeData=[t:Spitting Snake,r:1/2/3]{{aoe=[[1]] creature}}{{save=vs. poison with varying bonus/penalty negates}}{{effects=Spitting varieties of snakes bite their victims and can shoot poisonous spittle at a single target within 30 feet. Their poison is identical to normal poisonous snakes (see above). Typical species include the African spitting cobra, which can spit up to 15 feet. Its spittle can blind victims that fail a saving throw vs. poison. The blindness wears off after 2-12 hours.}}'},
+ {name:'Steam-Mephit-Rain',type:'Power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Steam Mephit causes\nScalding Rain}}{{splevel=Power}}{{school=Power}}Specs=[Steam-Mephit-Rain,Power,0H,Evocation]{{components=S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[20ft.sq](!rounds --aoe @{selected|token_id}|square|feet|0|20||acid)}}{{save=None}}{{damage=[2d6](!\\amp#13;\\amp#47;gmroll 2d6)}}SpellData=[w:Steam Mephit Rain,sp:5,cs:S]{{effects=Once per day a steam mephit may create a rainstorm of boiling water over a 20-by 20-foot area. This storm inflicts 2d6 points of damage to all victims caught in the area of effect, with no saving throw allowed.}}'},
+ {name:'Steam-Mephit-Water-Jet',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Steam Mephit breathes out \na Boiling Water Jet}}{{splevel=Breath Weapon}}{{school=Power}}Specs=[Steam Mephit Jet,Power,0H,Breath Weapon]{{components=None}}{{time=1 every 2 rounds}}{{range=[20 ft](!rounds --aoe @{selected|token_id}|bolt|feet|0|20|1|lightning --target caster|@{selected|token_id}|timer|1|-1|Counting down until Water Jet can be breathed again|stopwatch)}}{{duration=Instantaneous}}{{aoe=1 creature}}{{save=None}}{{damage=Automatic hit [1d3](!\\amp#13;\\amp#47;gmroll 1d4+1 HP damage)HP, and [50% chance](!\\amp#13;\\amp#47;gr 1d100\\lt50 chance of stunning) of [stunning](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the victim?|token_id}|Stunned|+1|-1|Stunned by heat damage \\amp considered prone|back-pain) for 1 round, cumulative}}SpellData=[w:Steam Mephit Water Jet,sp:0,cs:None,pd:-1]{{effects=A scalding jet of water every other round; no limit to the number of times per day this can be used. This jet has a 20-foot range and automatically hits its target. Damage is 1d3 points (no saving throw) with a 50% chance of stunning the victim for one round.}}{{Use=Display the area of effect using the Range button (also sets timer to count down 1 round to next breath available). Then roll damage using the damage dice roll button, then use the percentage dice roll button and if less than 50% add stunned effect using the stunned button and selecting the victim\'s token}}'},
+ {name:'Target-power',type:'',ct:'0',charge:'uncharged',cost:'0',body:'/w gm @{selected|token_name} targeted @{target|target1|token_name} with the power @{selected|spelltomem}\n!rounds --addtargetstatus @{target|target1|token_id}|@{selected|Spell-cast}|@{selected|Spell-duration}|@{selected|Spell-direction}|@{selected|Spell-msg}|@{selected|Spell-marker}'},
+ {name:'Target-user',type:'',ct:'0',charge:'uncharged',cost:'0',body:'/w gm @{selected|token_name} used the power @{selected|spelltomem} on themselves\n!rounds --addtargetstatus @{selected|token_id}|@{selected|Spell-cast}|@{selected|Spell-duration}|@{selected|Spell-direction}|@{selected|Spell-msg}|@{selected|Spell-marker}'},
+ {name:'Teleport-Other',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'{{}}Specs=[Teleport-Other,Power,0H,Alteration]{{}}SpellData=[w:Teleport Other,sp:2,cs:SpellData=[w:Teleport Other,sp:10,cs:S]{{}}%{MU-Spells-DB|Teleport}'},
+ {name:'Thunder+Lightning',type:'Power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.wandTemplate+'}{{title=Thunder \\amp Lightning}}{{subtitle=Power}}{{School=Alteration}}Specs=[Thunder+Lightning,Power,0H,Alteration]{{Components=V,M}}{{Casting Time=[[4]]}}{{Range=[[0]]}}{{Duration=[Fail save](!magic --message standard|@{selected|token_id}|Thunder \\amp Lightning|Stunned and deafened by a thunderclap and take \\amp#91;[{ 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1]\\amp#93;HP damage from a *lightning strike*|\\amp#13;!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is stunned?|token_id}|Thunderclap stun|\\amp#91;[1d2]\\amp#93;|-1|Stunned by a thunderclap|lightning-helix) stunned for 1d2 rounds, deafened for another 1d2 rounds, and take 8d6 damage (1s \\amp 2s count as 3s).\n[Make save](!magic --message standard|@{selected|token_id}|Thunder \\amp Lightning|Deafened by a thunderclap and take **\\amp#91;[floor\\amp#40;\\amp#91;[{ 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1+ { 1d6, {3} }k1]\\amp#93;/2\\amp#41;]\\amp#93;HP** damage from a *lightning strike* already halved|\\amp#13;!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is deafened?|token_id}|Thunderclap deaf|\\amp#91;[1d4]\\amp#93;|-1|Deafened by a thunderclap|interdiction) just deafened for 1d4 rounds and taken half of 8d6HP damage (1s \\amp 2s counted as 3s)}}{{Area of Effect=[Thunderclap Cone 40ft x 20ft](!rounds --aoe @{selected|token_id}|cone|feet|0|40|20|lightning)\n[Lightning Bolt](!rounds --aoe @{selected|token_id}|bolt|feet|0|80|5|lightning)\nor [Lightning Fork](!rounds --aoe @{selected|token_id}|bolt|feet|0|40|10|lightning)\nall creatures within area}}{{Save=Save vs. Staves, success just deafened for 1d4 rounds and half damage, else stunned for 1d2 \\amp deafened for 1d2 more and take 8d6HP damage)}}SpellData=[w:Thunder+Lightning,sp:4,cs:VM]{{desc=Both a cone of deafening noise, 5 feet wide at the apex, 40 feet long, and 20 feet wide at a point farthest from the source, and a lightning bolt 80ftx5ft (optionally forked to 40ftx10ft), spring forth from the staff. All creatures within this area, wholly or partially, must roll a successful saving throw vs. rods, staves, and wands or be affected as stated above.}}{{Use=Select the relevant areas of effect, using the displayed marker to change the direction of the areas. Then, depending on the results of saving throws, use the relevant duration buttons and set status markers on the appropriate victims and roll damage.}}'},
+ {name:'Thunderclap',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Thunderclap}}{{splevel=Power}}{{school=Alteration}}Specs=[Thunderclap,Power,0H,Alteration]{{components=V,M}}{{time=[[2]]}}{{range=[[0]]}}{{duration=[Fail save](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is stunned?|token_id}|Thunderclap stun|\\amp#91;[1d2]\\amp#93;|-1|Stunned by a thunderclap|lightning-helix) stunned for 1d2 rounds, deafened for another 1d2 rounds\n[Make save](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is deafened?|token_id}|Thunderclap deaf|\\amp#91;[1d4]\\amp#93;|-1|Deafened by a thunderclap|interdiction) just deafened for 1d4 rounds}}{{aoe=[Cone 40ft x 20ft](!rounds --aoe @{selected|token_id}|cone|feet|0|40|20|lightning), all creatures within area}}{{save=vs. Staves, success just deafened for 1d4 rounds, else stunned for 1d2 \\amp deafened for 1d2 more)}}SpellData=[w:Thunderclap,sp:2,cs:VM]{{effects=A cone of deafening noise, 5 feet wide at the apex, 40 feet long, and 20 feet wide at a point farthest from the source. All creatures within this cone, wholly or partially, must roll a successful saving throw vs. rods, staves, and wands or be stunned for 1d2 rounds (unable to attack during this time) and unable to hear for 1d2 additional rounds. Those who save are unable to hear for 1d4 rounds, but suffer no loss of attacks.}}'},
+ {name:'Turn-undead',type:'Power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} attempts to\nTurn Undead\nas a level @{selected|pr-casting-level} @{selected|class3}}}{{splevel=Power}}{{school=Necromancy}}Specs=[Turn-Undead,Power,1H,Necromancy]{{components=V,S}}{{time=[[10]]}}{{range=0}}{{duration=Until broken}}{{aoe=Undead within line of sight}}{{save=See turning table}}{{reference=PHB p103}}{{damage=[Roll 1d20](!\\amp#13;\\amp#47;r 1d20 turning undead) then [Turn them](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select undead|token_id}|Turned|99|0|Turned undead, flee if free-willed, stand aside if controlled|screaming)}}SpellData=[w:Turn Undead,sp:10,cs:VS]{{effects=**Remember that Paladins turn as a Priest of 2 levels lower.**\nAttempting to turn counts as an action, requiring one round and occurring during the character\'s turn in the initiative order (thus, the undead may get to act before the character can turn them). The mere presence of the character is not enough--a touch of drama from the character is important. Speech and gestures are important, so the character must have his hands free and be in a position to speak. However, turning is not like spellcasting and is not interrupted if the character is attacked during the attempt.\nTo resolve a turning attempt, look on Table 61. Cross-index the Hit Dice or type of the undead with the level of the character (two levels lower for a paladin). If there is a number listed, roll 1d20. If the number rolled is equal to or greater than that listed, the attempt is successful. If the letter "T" (for "turned") appears, the attempt is automatically successful without a die roll. If the letter "D" (for "dispel") is given, the turning utterly destroys the undead. A dash (--) means that a priest or paladin of that level cannot turn that type of undead. A successful turn or dispel affects 2d6 undead. If the undead are a mixed group, the lowest Hit Dice creatures are turned first.\nOnly one die is rolled regardless of the number of undead the character is attempting to turn in a given round. The result is read individually for each type of undead.}}{{material=The Priest\'s holy symbol}}'},
+ {name:'Underwater-Infravision',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Underwater Infravision}}{{splevel=Power}}{{school=Alteration}}Specs=[Underwater Infravision,Power,0H,Alteration]{{components=None}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Permanent}}{{aoe=Special}}{{healing=[See more clearly](!rounds --target caster|@{selected|token_id}|Underwater-Infravision|99|0|Infravision only while underwater|ninja-mask) but only underwater}}{{save=None}}SpellData=[w:Underwater Infravision,sp:0]{{desc=Same as the elf infravision ability, but only works underwater; an elven or half-elven character with this power has Infravision of doubled range, to 120\', only underwater.}}'},
+ {name:'Water-Breathing-24hr',type:'Power',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses\n24hr Water Breathing for Self\nas a Power}}{{splevel=Power}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Water-Breathing-24hr,Power,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=[[0]]}}{{duration=24 hours, self-renewing if asleep or unconcious}}{{aoe=Caster}}{{save=None}}{{reference=PHB p215}}{{healing=[Grant gills](!rounds --target caster|@{selected|token_id}|Water-Breathing|99|0|Breath water like a fish|ninja-mask)}}SpellData=[w:Water-Breathing-24hr,sp:6,cs:VS]{{effects=The recipient is able to breathe under water freely for 24 hours. If rendered fall asleep underwater or are rendered unconcious underwater, the power automatically renews as necessary. The power cannot be dispelled.\nNote that the spell does not prevent the recipient creature from breathing in its natural element.}}'},
+ {name:'Water-Breathing-Self',type:'Power',ct:'6',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nWater Breathing for Self\nas a level @{selected|Casting-Level} caster}}{{splevel=Power}}{{school=Alteration}}{{sphere=Elemental(Water)}}Specs=[Water-Breathing,Power,1H,Alteration]{{components=V,S}}{{time=[[6]]}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]] hours}}{{aoe=Caster}}{{save=None}}{{reference=PHB p215}}{{healing=[Grant gills](!rounds --target caster|@{selected|token_id}|Water-Breathing|[[60*@{selected|casting-level}]]|-1|Breath water like a fish|ninja-mask)}}SpellData=[w:Water-Breathing-Self,sp:6,cs:VS]{{effects=The recipient is able to breathe under water freely for the duration of the spell--i.e., one hour for each experience. The power cannot be dispelled.\nNote that the spell does not prevent the recipient creature from breathing in its natural element.}}'},
+ {name:'Whelm-Detect-Evil',type:'ItemPower',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Whelm casts\nDetect-Evil\nas a level 12 caster}}{{splevel=Power}}{{school=Divination}}{{sphere=All}}Specs=[Whelm-Detect-Evil,ItemPower,0H,Divination]{{components=V,S}}{{time=[[1]]round}}{{range=[[0]]}}{{duration=[[70]] rounds}}{{aoe=[10ft x 120yds path](!rounds --aoe @{selected|token_id}|bolt|feet|0|360|10|magic)}}{{save=None}}{{healing=[Evil radar on](!rounds --target caster|@{selected|token_id}|Detect-Evil|70|-1|Whelm is Detecting Evil|aura)}}SpellData=[w:Whelm-Detect-Evil,sp:10,cs:VS]{{effects=This spell discovers emanations of evil, or of good in the case of the reverse spell, from any creature, object, or area. Character alignment, however, is revealed only under unusual circumstances: characters who are strongly aligned, who do not stray from their faith, and who are of at least 9th level might radiate good or evil *if intent upon appropriate actions.* Powerful monsters, such as rakshasas or ki-rin, send forth emanations of evil or good, even if polymorphed. Aligned undead radiate evil, for it is this power and negative force that enable them to continue existing. An evilly cursed object or unholy water radiates evil, but a hidden trap or an unintelligent viper does not. \nThe degree of evil (dim, faint, moderate, strong, or overwhelming) and possibly its general nature (expectant, malignant, gloating, etc.) can be noted. If the evil is overwhelming, the priest has a 10% chance per level of detecting its general bent (lawful, neutral, or chaotic). The duration of a *detect evil *(or *detect good*) spell is one turn plus five rounds per level of the priest. Thus, a 1st-level priest can cast a spell with a 15-round duration, a 2nd-level priest can cast a spell with a 20-round duration, etc. The spell has a path of detection 10 feet wide in the direction the priest is facing. The priest must concentrate--stop, have quiet, and intently seek to detect the aura--for at least one round to receive a reading}}{{materials=The spell requires the use of the priest\'s holy symbol, with the priest holding it before him.}}\n!setattr --charid @{selected|character_id} --silent --Spell-cast|Detect-Evil --Spell-direction|-1 --Spell-duration|70 --Spell-msg|Detecting Evil --Spell-marker|aura'},
+ {name:'Whelm-Detect-Good',type:'ItemPower',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Whelm casts\nDetect Good\nas a level 12 caster}}{{splevel=Power}}{{school=Divination}}{{sphere=All}}Specs=[Whelm-Detect-Good,ItemPower,0H,Divination]{{components=V,S}}{{time=[[1]]round}}{{range=[[0]]}}{{duration=[[70]] rounds}}{{aoe=[10ft x 120yds path](!rounds --aoe @{selected|token_id}|bolt|feet|0|360|10|magic)}}{{save=None}}{{healing=[Good radar on](!rounds --target caster|@{selected|token_id}|Detect-Good|70|-1|Whelm is Detecting Good|aura)}}SpellData=[w:Whelm-Detect-Good,sp:10,cs:VS]{{effects=This spell discovers emanations of evil, or of good in the case of the reverse spell, from any creature, object, or area. Character alignment, however, is revealed only under unusual circumstances: characters who are strongly aligned, who do not stray from their faith, and who are of at least 9th level might radiate good or evil *if intent upon appropriate actions.* Powerful monsters, such as rakshasas or ki-rin, send forth emanations of evil or good, even if polymorphed. Aligned undead radiate evil, for it is this power and negative force that enable them to continue existing. An evilly cursed object or unholy water radiates evil, but a hidden trap or an unintelligent viper does not. \nThe degree of evil (dim, faint, moderate, strong, or overwhelming) and possibly its general nature (expectant, malignant, gloating, etc.) can be noted. If the evil is overwhelming, the priest has a 10% chance per level of detecting its general bent (lawful, neutral, or chaotic). The duration of a *detect evil *(or *detect good*) spell is one turn plus five rounds per level of the priest. Thus, a 1st-level priest can cast a spell with a 15-round duration, a 2nd-level priest can cast a spell with a 20-round duration, etc. The spell has a path of detection 10 feet wide in the direction the priest is facing. The priest must concentrate--stop, have quiet, and intently seek to detect the aura--for at least one round to receive a reading}}{{materials=The spell requires the use of the priest\'s holy symbol, with the priest holding it before him.}}\n!setattr --charid @{selected|character_id} --silent --Spell-cast|Detect-Good --Spell-direction|-1 --Spell-duration|70 --Spell-msg|Detecting Good --Spell-marker|aura'},
+ {name:'Whelm-Locate-Object',type:'ItemPower',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Whelm casts\nLocate Object\nas a level 12 caster}}{{splevel=Power}}{{school=Divination}}{{sphere=Divination}}Specs=[Whelm-Locate-Object,ItemPower,1H,Divination]{{components=V,S}}{{time=[[1]] turn}}{{range=[180 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|360||magic|true)}}{{duration=[[8]] hours}}{{aoe=[[1]] object}}{{save=None}}SpellData=[w:Whelm Locate Object,sp:1,cs:VS]{{effects=This spell helps locate a known or familiar object. The priest casts the spell, slowly turns, and will sense when he is facing in the direction of the object to be located, provided the object is within range--for example, 90 yards for 3rd-level priests, 100 yards for 4th, 110 yards for 5th, etc. The spell locates such objects as apparel, jewellery, furniture, tools, weapons, or even a ladder or stairway. Once the caster has fixed in his mind the items sought, the spell locates only that item. Attempting to find a specific item, such as a kingdom\'s crown, requires an accurate mental image. If the image is not close enough to the actual item, the spell does not work; in short, desired but unique objects cannot be located by this spell unless they are known by the caster. The spell is blocked by lead.\nThe reversal, obscure object, hides an object from location by spell, crystal ball, or similar means for eight hours. The caster must touch the object being concealed.\nNeither application of the spell affects living creatures.}}{{materials=Whelm}}'},
+ {name:'Whelm-Shockwave',type:'ItemPower',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} creates a\nShockwave\nwith Whelm}}{{splevel=Power}}{{school=Alteration}}Specs=[Whelm-Shockwave,ItemPower,1H,Alteration]{{components=S}}{{time=[[10]]}}{{range=[[0]]}}{{duration=[[1]] turn}}{{aoe=[Up to 120ft diameter](!rounds --aoe @{selected|token_id}|circle|feet|0|||lightning|true)}}{{save=[Negates](!\\amp#13;\\amp#47;gmroll 1d20 save vs staves or stunned)}}{{healing=[Stunning!](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Select first shocked creature|token_id}|Whelm-Stunned|10|-1|Stunned roll save vs Staves again|fishing-net)}}SpellData=[w:Whelm Shockwave,sp:10,cs:S]{{effects=You can use a round to strike the ground with *Whelm* and send a ***Shock Wave*** out from the point of impact. Each creature of your choice on the ground within [[60]] feet of that point must succeed on a saving throw vs. Staves or become stunned for [[1]] turn. A creature can repeat the saving throw at the end of each round, ending the effect on itself on a success. Once used, this property can\'t be used again until the next dawn.}}'},
+ {name:'Whirlwind',type:'Power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Whirlwind}}Specs=[Whirlwind,Power,0H,Innate Ability]{{Speed=[[3]]}}{{save=Vs Breath Weapon to halve}}{{Recharge=[Start recharging](!rounds --target caster|@{selected|token_id}|AE-Whirlwind|\\amp#91;[3+1d3]\\amp#93;|-1|Whirlwind building|stopwatch)}}SpellData=[w:Whirlwind,sp:3,cs:S]{{desc=The most feared power of an air elemental is its ability to form a whirlwind upon command. Using this form, the air elemental appears as a truncated, reversed cone with a 10 foot bottom diameter and 30 foot top diameter. The height of the whirlwind depends on the Hit Dice of the elemental. An air elemental of 8 Hit Dice will produce a whirlwind standing 40 feet tall; a 12 Hit Dice elemental produces a whirlwind standing 60 feet tall; and a 16 Hit Dice elemental produces a whirlwind standing 80 feet tall. It takes one full turn to form and dissipate this cone.\nThis whirlwind lasts for one melee round. Each creature in the elemental\'s space must make a **saving throw vs Breath Weapon**. On a failure, creatures of 3 hit dice or less are killed (0 HP not stable). Creatures of more than 3 HD take [2d8](!\\amp#13;\\amp#47;gmroll 2d8 damage from whirlwind) bludgeoning damage and is flung up to [[20]] feet away from the elemental in a random direction and knocked prone. If a thrown target strikes an object, such as a wall or floor, the target takes an additional [10yds 1d6, 20yds 2d6](!\\amp#13;\\amp#47;gmroll \\amp#63;{How far|10,1|20,2}d6 damage from hitting wall) bludgeoning damage for every 10 feet it was thrown. If the target is thrown at another creature, that creature must succeed on a Dexterity saving throw or take the same damage and be knocked prone.\nIf the saving throw is successful, the target takes half the bludgeoning damage and isn\'t flung away or knocked prone.\nIf, because of overhead obstructions, the whirlwind fails to reach its full height, it can only sweep up creatures under 2 Hit Dice and do 1-8 points of damage to all others in its cone.}}'},
+ {name:'WoF-Burning-Hands',type:'Power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Wand of Fire\nBurning Hands}}{{splevel=Magic Item Power}}{{school=Evocation}}Specs=[Burning Hands,Power,1H,Evocation]{{components=V,M}}{{time=[[0]]}}{{range=12ft}}{{duration=Instantaneous}}{{aoe=[Fan 10ft wide](!rounds --aoe @{selected|token_id}|cone|feet|0|12|10|fire|true)}}{{save=None}}{{reference=DMG p154}}SpellData=[w:WoF-Burning-Hands,sp:0,cs:VM]{{effects=**Note: specs different from spell.** The wand emits a [[120]]degree fan-shaped sheet of fire [[10]] feet wide at its end and [[12]] feet long. Each creature touched suffers [[6]] HP of damage. The sheet of fire appears instantly, shoots forth dark red flames, and snuffs out in less than one second.}}'},
+ {name:'WoF-Cone-of-Cold',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Wand of Frost\nCone of Cold}}{{splevel=Power}}{{school=Evocation}}Specs=[WoF Cone of Cold,Power,1H,Evocation]{{components=V,M}}{{time=[[2]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[Cone 60ft x 20ft](!rounds --aoe @{selected|token_id}|cone|feet|0|60|20|cold)}}{{save=Halves}}SpellData=[w:Cone of Cold,lv:6,sp:2,cs:VM]{{effects=White crystalline motes spray forth from the wand in a cone with a 60-foot length and a terminal diameter of 20 feet. The initiative modifier is +2, and the effect lasts just one second. The temperature is -100 degrees F., and damage is [6d6](!\\amp#13;\\amp#47;w gm Rolled \\amp#91;\\amp#91; { {1d6}, {1d6}, {1d6}, {1d6}, {1d6}, {1d6}, {2}, {2}, {2}, {2}, {2}, {2} }kh6 \\amp#93;\\amp#93;, treating all 1s rolled as 2s), treating all 1s rolled as 2s (6d6, 12-36). The cost is two charges per use. Saving throw vs. wands is applicable.}}'},
+ {name:'WoF-Fireball',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Wand of Fire\nFireball}}{{splevel=Magic Item Power}}{{school=Evocation}}Specs=[Fireball,Power,1H,Evocation]{{components=V,M}}{{time=[[2]]}}{{range=160ft}}{{duration=Instantaneous}}{{aoe=[20ft radius](!rounds --aoe @{selected|token_id}|circle|feet|160|40|40|fire)}}{{save=vs. wand to halve damage}}SpellData=[w:WoF-Fireball,sp:2,cs:VM]{{effects=**Note: specs different from spell.** The wand coughs forth a pea-sized sphere that streaks out to the desired range (to a maximum of 160 feet) and bursts in a fiery, violet-red blast, just like the fireball spell. The initiative modifier is +2, and this expends [[2]] charges. The fireball inflicts [6d6 min 2/dice](!\\amp#13;\\amp#47;r {1d6,2+0d0}k1+{1d6,2+0d0}k1+{1d6,2+0d0}k1+{1d6,2+0d0}k1+{1d6,2+0d0}k1+{1d6,2+0d0}k1 points of fireball damage, save to half) points of damage, but all 1s rolled are counted as 2s (i.e., the burst causes 12-36 points). A saving throw vs. wand is applicable.}}'},
+ {name:'WoL-Lightning-Bolt',type:'Power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Wand of Lightning\nLightning Bolt}}{{splevel=Power}}{{school=Evocation}}Specs=[WoI Lightning Bolt,Power,0H,Evocation]{{components=V,M}}{{time=[[2]]}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=[Lightning Bolt](!rounds --aoe @{selected|token_id}|bolt|feet|0|80|5|lightning)\nor [Lightning Fork](!rounds --aoe @{selected|token_id}|bolt|feet|0|40|10|lightning)\nall creatures within area}}{{save=vs. Wand for half damage)}}{{damage=[Roll 6d6, 1s as 2s](!\\amp#13;\\amp#47;w gm \\amp#91;[{ {1d6}, {1d6}, {1d6}, {1d6}, {1d6}, {1d6}, {2}, {2}, {2}, {2}, {2}, {2} }k6]\\amp#93;HP damage)}}SpellData=[w:WoL Lightning Bolt,sp:2,cs:VM]{{effects=A bolt similar to that from a staff of thunder \\amp lightning is generated, but it is of 6d6 strength, causing 12-36 points of damage (rolls of 1 are counted as 2) to those who fail a saving throw. The stroke can be single or forked.}}'},
+ ]},
+ });
+
+ const handouts = Object.freeze({
+ RPGM_Release_Notes: {name:'RPGM Release Notes',
+ version:'1.501',
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGMaster Release Notes v1.501'
+ +'
'
+ +''
+ +'
RPGMaster Release Notes
'
+ +'
for version 1.5.01
'
+ +'
'
+ +'
Improved Initiative multi-tasking
'
+ +'
When using "Group" or "Individual" initiative types, and multiple players and the GM are all in the process of specifying what they are going to do in the next round to set the correct Turn Order priorities, the system now responds much more quickly to the user\'s button selection, returning a "Please Wait" message when necessary, and pushing back non-critical processing until after players have completed action selection. This means that Turn Order entries for each character / NPC / Creature may be delayed for a few seconds after the final button press occurs.
'
+ +'
Turn tracker rotation on/off
'
+ +'
A new command has been added to RoundMaster v4.043 to stop and start the rotation of the arrow circle around the token that is at the top of the Turn Tracker. The command !rounds --rotatetracker [ON/OFF] takes one optional parameter of \'on\' or \'off\'. If no parameter is specified, rotation is toggled between the two possible states. This command has been provided after performance issues were found with the rotating graphics on some computers.
'
+ +'
"Looks Like" template tag
'
+ +'
A new field tag {{Looks Like=...}} has been added for the RPGMaster templates RPGMspell and RPGMdefault, and all templates based on these (i.e. all tempates except RPGMmessage and RPGMattack templates). This field can be used to describe what a magic item looks like when it is first found. If the item is hidden as a different item using the GM\'s Add Items dialog and the template includes a "Looks Like" field tag with text, only the text in the Looks Like field will be shown to the player when viewed or used, up until the hidden item is revealed. The GM will always see the full item description whenever the GM views or uses an item, hidden or not.
'
+ +'
Auto-hiding of items
'
+ +'
A configuration flag can now be set by the GM using the !magic --config or !attk --config commands for "Auto-hiding Items". When set, and the GM adds an item to an container using the GM\'s Add Items dialog, and that item has a "Looks Like" field tag defined with text describing what the item looks like when first found (see previous note), the item will automatically be hidden as an item reflecting its generic item type (or supertype), or whatever has been set as its type using the "st:" data tag in the item definition. The GM can then specify when its true nature will be revealed (on viewing, on use, or manually by GM) using the other functions on the Add Items dialog.
'
+ +'
GM easy manual reveal for hidden items
'
+ +'
When a player character uses a hidden item, the GM is already passed a message in the Chat Window saying which item has been used, with a button to display the details of the item. If the item being used is actually a hidden item, when the GM displays the item description a button will appear for the GM to manually reveal the hidden item, if they so desire. This saves the GM having to use the Add Items dialog to manually reveal items.
'
+ +'
Default item class to "Miscellaneous"
'
+ +'
If the GM created new magic items in their own database, the class was restricted to those defined in the Spells & Magic Items Database Help handout. It is now possible to invent totally new item classes - all item classes not defined in the APIs will now default to working the same way as the "Miscelaneous" item class - that is they will appear in Miscellaneous menu lists, and can be used by any character class or creature that is defined in the databases as being able to use magic items.
'
+ +'
Alphabeticised item lists
'
+ +'
By default, all lists of magic items given on the GM\'s Add Items dialog and on the Player\'s Edit Weapons & Armour and Edit Magic Items dialogs are now alphabeticised. Select the letter from the first drop down to see a list of all items starting with that letter in a second drop down. The alphabetical lists can be returned to just show all items in one big list by using the !magic --config or !attk --config dialog, or for the GM using the "alpha true/false" button at the top of the Add Items dialog.
'
+ +'
AC Item combination rule data
'
+ +'
Data tags to specify which other types of AC item any particular item can be used in combination with, or not, can now be specified in the ACData section of an item definition using the rules: data tag. After the tag:
'
+ +'
- preceeding an item type, supertype, or name with \'-\' means this item cannot combine with that type of item
'
+ +'- preceeding an item type, supertype, or name with \'+\' means it can always be used with it
'
+ +'- an item with \'-acall\' will not combine with any other AC items except those with a \'+\'
'
+ +'- an item with \'-magic\' will not combine with any magical armour
'
+ +'- an item with \'-shield\' will not combine with any form of shield
'
+ +'
See the Weapons & Armour Database Help handout for more information and examples.
'
+ +'
Improved Check AC dialog
'
+ +'
The Check AC dialog now explains the effect on AC of each item, even if the magical bonus or penalty is not displayed as part of the item name.
'
+ +'
Tidying Character Sheets
'
+ +'
Improved the function that examines Character Sheets in a campaign and removes any spurious objects created by the RPGMaster APIs so as to speed up processing.
'
+ +'
Custom Items database
'
+ +'
All custom magic items, ones that do not appear in any of the AD&D2e manuals, have been split out of the current databases and stored in a new database MI-DB-Custom. These can be viewed by extracting the custom item database using the !magic --extract-db MI-DB-Custom command. However, in this release all custom items are indistinguishable from other items in the campaign. A future release will include a configuration flag to exclude or include the custom database from use. All GM-created databases will be unaffected.
'
+ +'
Bug Fixes
'
+ +'
A number of bug fixes have been applied, including: fixed handing an undefined Race character sheet field; fixed magic helm ac modifiers; fixed --mod-weap selection using a named item; fixed GM display of a spell or a used item to whisper to the GM only rather than display to all players.
'
+ +'
Release v1.4.07
'
+ +'
Spells as Powers in Powerful items
'
+ +'
It has been possible to store Spells as Powers for a character (via the Token Setup / Add to Spellbook dialogue) for a little while. It is now also possible to do this for items that can store powers. The GM can add powers to any item that has an API button that calls the command !magic --cast-spell MI-POWERS|@{selected|token_id}
using the Add Item / Store Spells/Powers in MI button, and the dialogue presented will now allow spells (both Wizard & Priest) to be stored as powers in the item to be cast at a specified level and a specified number of times per day by the character, recharging after a long rest. Note that in order to implement this, if powerful items like this are stored, picked up, or transfered to another character using MI menu / Search or MI menu / Store the powers will be restored to full charges as if a long rest had occurred (I\'ve used the field that passed the current charges left to transfer the level of casting instead).
'
+ +'
Arced Areas of Effect
'
+ +'
It is now possible to specify areas of effect that are arcs of 90 or 180 degrees. Just use the \'ARC90\' or \'ARC180\' area definition when calling the !rounds --aoe
command.
'
+ +'
Drag & Drop Creatures for Bags of Tricks
'
+ +'
I have added Drag & Drop creature definitions for all the creatures that can be summoned by all three types of the standard Bags of Tricks defined in the DMG (all of which are non-magical mammals). When a character uses a Bag of Tricks, a dice can be rolled to determine which creature appears of those that are possible for that type of bag, and the GM can then create a new character sheet in the Journal, give it an appropriate avatar image from their loaded art, and Drag & Drop the creature onto the map, using the presented dialogue to choose the appropriate creature.
'
+ +'
Macro-accessible Item Quantity
'
+ +'
The character sheet now has an attribute which holds the current number of charges left of the currently selected magic item, held in the attribute MIct|max. To see an example of how this is used, see the definition for the Boots-Winged item in the MI-DB database (and the associated Boots-of-Flying-turn effect in the Effects-DB database) which can fly for 120 minutes per day but which can be in several sessions. This sets a status round counter to the value of MIct|max, then counts down from this deducting 1 charge per round. If the character stops flying, the GM ends the status and the charges stop deducting. If there are charges left, the character can fly again for up to that duration. The charges then recharge over a long rest (rather than 24 hours, which it should be).
'
+ +'
New Effect ^^Duration^^ attribute tag
'
+ +'
In support of the Macro-accessible Item Quantity introduced above, the Effect attribute tag ^^Duration^^ has also been added. ^^Duration^^ specified as a tag in a "-turn" Effect macro will resolve to the number of rounds that have passed since the last "-turn" call, which is normally 1 round. However, if the GM uses the Maintenance Menu to set a new Round number in the Turn Tracker, ^^Duration^^ in any running Effect will resolve to the number of rounds that have passed (the difference between the previous and new round numbers, positive only). This allows the "-turn" Effect to, for instance in the Winged Boots example used above, reduce the remaining charges of the boots by the number of rounds passed. This allows the GM to skip over the rounds it takes for the character using the boots to fly somewhere, without having to go through each round individually (which would be boring for everyone).
'
+ +'
For Effect types "-start", "-end", "-add", "-dancing", "-inhand", and "-sheath", ^^Duration^^ always resolves to zero.
'
+ +'
Non-divisable Charged & Uncharged items
'
+ +'
Items that are Recharging, Rechargeable, Absorbing etc are always picked up or stored as a complete, singular item with all their charges intact which cannot be divided. However, Charged and Uncharged items (and Cursed, which is equivalent to Uncharged) with more than one charge present a menu on Searching or Storing allowing the character to pick or put one, all, or a specified number of the "charges" - which assumes the item can logically be divided. This is deemed sensible for potions and scrolls but, for instance, for a non-rechargeable wand with several charges it would be impossible to "snap the wand in two" and pick up or store only some of the charges, leaving the rest behind. So I\'ve added two new types of item: "Discharging" (which is a non-divisable Charged item) and "Cursed-Uncharged" (an Uncharged item that is Cursed such that it cannot be divided or is otherwise not sensible to divide). It is also the case that only divisable items (i.e. Charged, Uncharged & Cursed - but not Cursed-Uncharged) can stack in the character\'s item bag, as others will not be able to be un-stacked as they are not divisable. Uncharged items (such as weapons, ammo and armour) and Charged items (such as potions and scrolls) remain both divisable and stackable.
'
+ +'
Bug Fixes
'
+ +'
A number of bug fixes have been applied, including the fix to the Token Setup / Add to Spellbook button that will now work.
'
+ +'
Release v1.4.05
'
+ +'
Magic Item Bags
'
+ +'
Some magic items are in fact bags that hold other magic items: e.g. a Bag of Holding, or a Bag of Beans. An item specification can now be written to automatically create a "magic item character sheet" which can hold other items, and even be specified with a starting set of items such as the beans in the bag. The character sheet so created will be controlled by and in the journal of the character that has the magic item bag, and if looted or given away, the ownership moves with it (requires the new owner to view or use the magic item bag first. See the Magic Database Help handout for more details.
'
+ +'
DM Info in Roll Templates
'
+ +'
Any Roll Template based on any RPGM template (except RPGMattack and RPGMmessage) can now have a line tag of "GM Info=" included, the contents of which will only be displayed if the GM is one of the recipients for the message: e.g. {{GM Info=This will be displayed if the GM is one of the recipients of this Roll Template message}}. This can be useful to include information you only want the GM to see, for instance about how to play a spell or how to tailor a magic item.
'
+ +'
Bug Fixes
'
+ +'
Fixes to issues with manual updates to saving throws, changing the rings on each hand using the Change Weapon dialogue and searching, looting and storing items and equipment.
'
+ +'
',
+ },
+ RPGM_Templates_Handout: {name:'RPGMaster Library Help',
+ version:1.03,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGMaster Library Help v1.03'
+ +'
'
+ +''
+ +'
RPGMaster Library and Templates
'
+ +'
for all RPGMaster APIs
'
+ +'
1. General RPGMaster Library information
'
+ +'
The RPGMaster Library API provides the data and rule-set processing for a specific RPG version and Roll20 Character Sheet for the RPGMaster series of APIs. This particular Library supports the Advanced Dungeons and Dragons v2e RPG, and the Advanced D&D 2e Character Sheet by Peter B.
'
+ +'
The functions and data in the Library cannot be accessed directly by the GM or Players (with the exception of the RPGMaster Roll Templates). It does not support any API commands directly, but supports the functioning of the API commands provided by other RPGMaster APIs: InitiativeMaster, AttackMaster, MagicMaster and CommandMaster, to the extent that these APIs will not function without the Library being loaded. Note: RoundMaster does not have any RPG-version specific aspects, is independent of the Library, and does not require a RPGMaster Library to be loaded to function.
'
+ +'
The Library does Roll Template processing for RPGMaster-defined Roll Templates. These can be used by GMs to create their own Chat menus and displays. See the descriptions in Section 2 for how to access and use these templates.
'
+ +'
The Library also provides a number of objects and functions that can be called from other APIs. These include an extensive Character Sheet table management suite described in Section 3 below, for table structures defined by The Aaron in various standard Roll20 Character Sheets, such as the Advanced D&D 2e character sheet by Peter B. There are a number of other useful functions, which are described in Section 3.
'
+ +'
Contents
'
+ +'
1. General RPGMaster Library Information
'
+ +'2. RPGMaster Roll Templates
'
+ +' 2.1 User-Selectable Template Display
'
+ +' 2.2 Colour, Padding and Image Override Field Tags
'
+ +' 2.3 Template Definitions
'
+ +' RPGMattack
'
+ +' RPGMspell
'
+ +' RPGMmessage
'
+ +' RPGMdefault
'
+ +'3. API Library Accessible Functions
'
+ +' 3.1 Get Character Sheet Field Map and Global Data
'
+ +' 3.2 Manage Character Sheet Tables
'
+ +' Table Management Functions
'
+ +' Table Object Methods
'
+ +' 3.3 Attribute Management
'
+ +' 3.4 Database Management
'
+ +'
'
+ +'
2. RPGMaster Roll Templates
'
+ +'
Roll Templates are standard Roll20 functionality, often provided by various Character Sheet versions. The RPGMaster Library provides RPGMaster-specific versions of Roll Templates to support gameplay using the RPGMaster series of APIs. Of course, they can also be used for other purposes by the GM to support their design for gameplay, and by other APIs that might be loaded alongside the RPGMaster Library API. The list of those provided is:
'
+ +'
'
+ +' Template | Based on | Description |
'
+ +' RPGMattack | RPGMattack | Format the results of attacks, Melee or Ranged |
'
+ +' RPGMpotion | RPGMspell | Display the details of a potion, oil or other consumable liquid |
'
+ +' RPGMspell | RPGMspell | Display the specification of a spell or power |
'
+ +' RPGMscoll | RPGMspell | Display the details of a scroll or book |
'
+ +' RPGMmessage | RPGMmessage | Display a formatted message |
'
+ +' RPGMwarning | RPGMdefault | Display a warning message in a bold format |
'
+ +' RPGMweapon | RPGMdefault | Display the specification of a weapon of any type |
'
+ +' RPGMammo | RPGMdefault | Display the specification of ammunition for a Ranged weapon |
'
+ +' RPGMarmour | RPGMdefault | Display the specifications of any form of armour |
'
+ +' RPGMring | RPGMdefault | Display the specifications of a ring |
'
+ +' RPGMwand | RPGMdefault | Dosplay the specifications of a wand, stave or rod |
'
+ +' RPGMitem | RPGMdefault | Display the specifications of any magic item |
'
+ +' RPGMclass | RPGMdefault | Display the details of a character class |
'
+ +' RPGMmenu | RPGMdefault | Display a menu of actions that a Player or GM can perform |
'
+ +' RPGMdefault | RPGMdefault | A default template that can display any form of information |
'
+ +'
'
+ +'
The templates are built upon four base templates: RPGMattack, RPGMspell, RPGMmessage, and RPGMdefault. However, each individual template can have different colour swatches and background images. It is also possible for the GM to use special template field tags to change the colours and background images of various parts of the templates, as described below.
'
+ +'
2.1 User-Selectable Template Display Options
'
+ +'
In the API configuration menu, opened using !attk --config or !magic --config, the GM can choose whether the default display of RPGMaster Roll Templates for everyone is Fancy, meaning the system uses background textures and images to make the chat templates look interesting, or Plain, which means the default display is of coloured templates but without textures or images.
'
+ +'
In addition, each Player can choose their own options: at the top right of every menu or message displayed in the chat using a RPGMaster Template is a cog wheel. Clicking this cog wheel will display an options dialog for the Player with three options - Menus with Images, Plain Menus, and Dark Mode Menus. The Player can select one of the options, and the current and all future menus and messages using RPGMaster Roll Templates will be displayed for that particular Player using this new option. The option persists for that Player between gameplay sessions.
'
+ +'
Note: if use of a template includes any of the colour or image field tags (outer image, title image or body image) these images will always appear regardless of which option the Player chooses. The field tags always override the original template definition.
'
+ +'
2.2 Colour, Padding and Image Override Field Tags
'
+ +'
All RPGMaster templates can use the following field tags (with some exceptions as noted). The field tags are used in this way:
'
+ +'
{{field tag=... whatever you want to be in this field ...}}
'
+ +'
However, the fields in this table do not display data, but take the content of the field after the "=" as data for a CSS command to change the behavior of the template.
'
+ +'
'
+ +' shadow | drop shadow spec | The specification of the Template drop shadow for the outer box in any form of CSS units |
'
+ +' outer | color | The colour of the outer box of the template |
'
+ +' title box | color | The fill colour of the title box |
'
+ +' title text | color | The colour of the title text |
'
+ +' body box | color | The fill colour of the body box |
'
+ +' row box | color | The colour of the outline of each row box |
'
+ +' row light | color | The fill colour of alternate row boxs (light / dark / light / dark ...) |
'
+ +' row light text | color | The colour of alternate row text (light / dark / light / dark ...) |
'
+ +' row dark | color | The fill colour of alternate row boxs (light / dark / light / dark ...) |
'
+ +' row dark text | color | The colour of alternate row text (light / dark / light / dark ...) |
'
+ +' outer pad | padding spec | The padding of the outer box specified using any form of CSS measurements |
'
+ +' title pad | padding spec | The padding of the title box specified using any form of CSS measurements |
'
+ +' body pad | padding spec | The padding of the body box specified using any form of CSS measurements |
'
+ +' row pad | padding spec | The padding of each row box specified using any form of CSS measurements |
'
+ +' outer image | Image URL | The URL to an image in Roll20 which will be drawn behind the whole Template |
'
+ +' title image | Image URL | The URL to an image in Roll20 which will be drawn behind the title box |
'
+ +' body image | Image URL | The URL to an image in Roll20 which will be drawn behind the body of the Template |
'
+ +'
'
+ +'
The data passed with these field tags is one of four types: color, padding spec, shadow spec or image URL. Note, the CSS keyword is not needed in each case, just the data specification that would follow the keyword.
'
+ +'
Tip: In fact, you can sneak additional CSS keywords into the data - e.g. the title text colour could be \'{{title text=white; text-shadow: 1px 1px 1px gray}}\' which would sneak a drop-shadow onto the title text of the Template. This will not always work, but is worth trying.
'
+ +'
'
+ +' color | Can be any valid < color > specification that can be placed after a CSS < color > command: a named color, a RGB specification, a HSL specification, or any other valid syntax. |
'
+ +' padding spec | Can be any valid padding < length > specification that can be placed after a CSS < padding > command: relative units such as \'em\' or \'small\' or percentages, or can be absolute units such as \'px\' or \'cm\'. |
'
+ +' shadow spec | Can be any valid shadow < length > and < color > specification that can be placed after a CSS < box-shadow > command: relative units such as \'em\' or \'small\' or percentages, absolute units such as \'px\' or \'cm\'; and a named color, a RGB specification, an HSL specification, or any other valid syntax. |
'
+ +' Image URL | Must be a valid URL of a thumbnail image already loaded to the Roll20 image library - either your own or one you are provided with. |
'
+ +'
'
+ +'
2.3 Template Definitions
'
+ +'
RPGMattack
'
+ +'
As with any template, the text in any of the fields can be anything allowed by Roll20 in a macro or template, except where noted otherwise. If to be used with a RPGMaster API database, the Specs and Data fields must be configured in line with the relevant database documentation and placed between the template fields so as not to be seen by the Players when the Roll Template is displayed. This is a highly graphical template (even in Plain Mode) and the Field Tags are generally not displayed.
'
+ +'
'
+ +' Title / Name | Mandatory | The title text for the attack template. Either field tag can be used, and the tag is not displayed. |
'
+ +' Subtitle | Optional | The subtitle text for the attack template. The tag is not displayed. |
'
+ +' AC hit | Mandatory | The value of the Armour Class that has been successfully hit by the attack. Can be a Roll20 calculation and/or dice roll specification. If the "Crit Roll" and "Fumble Roll" field tags are to function correctly, the AC hit tag must include one Roll20 calculation field tagged as the Dice Roll e.g. matches ##[Dice roll]. |
'
+ +' Attk type | Optional | The type of damage done by the attack: S, P, B, or any combination of these. |
'
+ +' Dmg S Label | Optional | The label / title to display for the Dmg S field on the template. If not provided, it defaults to "S / M". Useful if using the template for attacks that result in some outcome other than damage to the opponent. |
'
+ +' Dmg S | Mandatory | The specification to display for damage to Small & Medium opponents. Can be numeric, a Roll20 calculation, dice roll specification, or even an API button specification. |
'
+ +' Dmg L Label | Optional | The label / title to display for the Dmg L field on the template. If not provided, it defaults to "L". Useful if using the template for attacks that result in some outcome other than damage to the opponent. |
'
+ +' Dmg L | Mandatory | The specification to display for damage to Large and larger opponents. Can be numeric, a Roll20 calculation, dice roll specification, or even an API button specification. |
'
+ +' Target AC | Optional | The Armour Class value of the targeted opponent. Only used for targeted attacks. Can be a Roll20 "@{target..." command, numeric value, calculation etc. |
'
+ +' Target SAC | Optional | The Armour Class value of the targeted opponent vs. Slashing attacks. Only used for targeted attacks. Can be a Roll20 "@{target..." command, numeric value, calculation etc. |
'
+ +' Target PAC | Optional | The Armour Class value of the targeted opponent vs. Piercing attacks. Only used for targeted attacks. Can be a Roll20 "@{target..." command, numeric value, calculation etc. |
'
+ +' Target BAC | Optional | The Armour Class value of the targeted opponent vs. Bludgeoning attacks. Only used for targeted attacks. Can be a Roll20 "@{target..." command, numeric value, calculation etc. |
'
+ +' Target HP | Optional | The current Hit Points of the targeted opponent. Must result in a numeric value. |
'
+ +' Target MaxHP | Optional | The maximum Hit Points of the targeted opponent. Must result in a numeric value. |
'
+ +' Result | Optional | A comparison function between any two other field tags, which are usually AC_Hit and Target_AC (note the underscores added). Can use any test from: = < > <= >= <> != e.g. AC_Hit<=Target_AC if true will give a green Success bar, if false will give a red Failure. |
'
+ +' SuccessCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Result comparison indicates success. Normally used to send an API command on a successful attack result |
'
+ +' FailCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Result comparison indicates failure. Normally used to send an API command on a failed attack result |
'
+ +' Crit Roll | Optional | Data must result in a numeric value which is compared to the Dice Roll value tagged in the AC Hit field. If Crit_roll<=Dice Roll, displays a green "Critical Hit!" bar. |
'
+ +' Fumble Roll | Optional | Data must result in a numeric value which is compared to the Dice Roll value tagged in the AC Hit field. If Fumble_roll>=Dice Roll, displays a red "Fumbled!" bar. |
'
+ +' Desc / Desc(1-9) | Optional | Up to 10 description fields can be added to the bottom of any RPGMaster attack template. The field tag is not displayed. These can, for example, hold reminders of special outcomes of the attack depending on the weapon or creature wielding it, or the roll achieved. |
'
+ +'
'
+ +'
RPGMspell, RPGMpotion & RPGMscroll
'
+ +'
As with any template, the text in any of the fields can be anything allowed by Roll20 in a macro or template, except where noted otherwise. For spell, potion and scroll descriptions especially it is quite often useful to include API Buttons in some of the fields to run certain RPGMaster API commands: this is especially the case if using the RoundMaster API and the commands !rounds --target to set status markers and timers and target spell effects, and/or !rounds --aoe to display ranges and areas of effect. If to be used with a RPGMaster API database, the Specs and Data fields must be configured in line with the relevant database documentation and placed between the template fields so as not to be seen by the Players when the Roll Template is displayed.
'
+ +'
'
+ +' Title / Name | Mandatory | The title text for the template. Either field tag can be used, and is not displayed. |
'
+ +' SPlevel | Optional | The level of the spell being cast. No need to provide for potions or scrolls. |
'
+ +' School | Optional | The school of the spell or spell-like effect. |
'
+ +' Range | Mandatory | The range of the spell or spell-like effect. |
'
+ +' Components | Mandatory | The components of the spell or spell-like effect. Often represented by a combination of the letters VSM. |
'
+ +' Duration | Mandatory | The duration of the spell or spell-like effect. |
'
+ +' Range | Mandatory | The range of the spell or spell-like effect. |
'
+ +' Time | Mandatory | The casting time or time until effect occurs of the spell or spell-like effect. |
'
+ +' AoE | Mandatory | The Area of Effect of the spell or spell-like effect. |
'
+ +' Save | Mandatory | The validity and outcome of any saving throw or other mitigating factors to the spell or spell-like effect. |
'
+ +' Healing | Optional | The healing or other beneficial effect of the spell or spell-like effect. |
'
+ +' Damage | Optional | The damage or other maleficent effect of the spell or spell-like effect. |
'
+ +' Reference | Optional | A reference to where more information can be found about the spell or spell-like effect. |
'
+ +' Materials | Optional | The material components required to cast the spell or spell-like effect. |
'
+ +' Effects | Optional | A description of the effects of the spell or spell-like effect. |
'
+ +' Use | Optional | Instructions for how to use the spell or spell-like effect. Especially useful for complex spells that require actions to occur in a particular sequence, have different means of achieving different effects in different circumstances, or have long-lasting effects. |
'
+ +' GM Info | Optional | Only appears if the message is for the GM (though other players included in the same message will also see it). Instructions for the GM on how to use the spell or spell-like effect, such as how to tailor for your own campaigns. |
'
+ +' Desc / Desc(1-9) | Optional | Up to 10 description fields can be added to the bottom of any RPGMaster spell, potion or scroll template. The field tag is not displayed. These can, for example, hold reminders of special outcomes of the spell depending on the creature targeted, or anything else the GM thinks useful but does not fit in any other field. |
'
+ +'
'
+ +'
RPGMmessage
'
+ +'
This template is mostly used internally by the RPGMaster APIs to send messages to the GM and Players. It provides a very simple template with a minimum of overhead. As with any template, the text in any of the fields can be anything allowed by Roll20 in a macro or template, except where noted otherwise. If to be used with a RPGMaster API database, the Specs and Data fields must be configured in line with the relevant database documentation and placed between the template fields so as not to be seen by the Players when the Roll Template is displayed.
'
+ +'
'
+ +' Title / Name | Optional | The title text for the template. In a Message Template, the title/name is optional and a message can appear without a title if so desired. Either field tag can be used, and is not displayed. |
'
+ +' Desc / Desc(1-9) | Optional | Up to 10 description fields can be defined, though usually it is just the one, which will contain the message. The field tag is not displayed. |
'
+ +'
'
+ +'
RPGMdefault
'
+ +'
All template definitions other than those described above use the base RPGMdefault template structure, with different colour swatches, textures and images. This template type is the most flexible, and will display pretty much any field tag that is added. Only a few are predefined, which provide the ability to structure the template. As with any template, the text in any of the fields can be anything allowed by Roll20 in a macro or template, except where noted otherwise. If to be used with a RPGMaster API database, the Specs and Data fields must be configured in line with the relevant database documentation and placed between the template fields so as not to be seen by the Players when the Roll Template is displayed.
'
+ +'
'
+ +' Title / Name | Mandatory | The title text for the template. Either field tag can be used, and the tag is not displayed. |
'
+ +' Subtitle | Optional | The subtitle text for the template. The tag is not displayed. |
'
+ +' Section / Section(1-9) | Optional | A section header, separating other user-defined field tags (not the Desc description field tags, which always appear at the bottom of the template). The field tag is not displayed, and the contents are centred in the row. |
'
+ +' Any User-defined tag | Optional | As many different user-defined field tags as are desired, using A-Z a-z - _ 0-9 and Space but always starting with an Alpha. |
'
+ +' Result | Optional | A comparison function between any two other field tags which have numeric data or calculations and attribute look-ups that result in numeric data. The field tag names to be compared should have underscores \'_\' instead of spaces. Can use any test from: = < > <= >= <> != e.g. AC_Hit<=Target_AC if true will give a green Success bar, if false will give a red Failure. |
'
+ +' SuccessCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Result comparison indicates success. Normally used to send an API command on a successful attack result |
'
+ +' FailCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Result comparison indicates failure. Normally used to send an API command on a failed attack result |
'
+ +' GM Info | Optional | Only appears if the message is for the GM (though other players included in the same message will also see it). Instructions for the GM on whatever the roll template is about, such as how to tailor a magic item for your own campaigns. |
'
+ +' Desc / Desc(1-9) | Optional | Up to 10 description fields can be defined, which will all be displayed at the bottom of the template in numeric order. The field tags are not displayed. |
'
+ +'
'
+ +'
3. API Library Accessible Functions
'
+ +'
In addition to the RPGM Templates described in Section 2, the RPGMaster Library provides a number of functions, objects and methods that might be of use to API authors, independantly of the RPGMaster series of APIs. These are described in this section. To access these, the functions can be accessed using the following syntax from other APIs:
'
+ +'
LibRPGMaster.function( parameters )
'
+ +'
Alternatively, so as not to need to reference the Library, and/or to facilitate an easily alterable and maintainable reference that can be changed in one place, the Library reference can be made within a function mapping, like this:
'
+ +'
const localFunctionName = (...a) => libRPGMaster.functionName(...a);
'
+ +'
The Library function can then be accessed using the localFunctionName in the API as required and, should the Library function call change, the change can be made in just one place.
'
+ +'
The rest of this Section describes the accessible functions, objects and methods.
'
+ +'
3.1 Get Character Sheet Field Map and Global Data
'
+ +'
The RPGMaster Library holds RPG-version-specific data which other APIs can access, and a map of the important fields on the Roll20 Character Sheet version supported. References to each of these data items can be acquired using the getRPGMap() function:
'
+ +'
[fields,RPGMap] = getRPGMap()
'
+ +'
This function does not take any parameters, but returns an array of two object references:
'
+ +'
'
+ +'
'
+ + 'dbNames | An array of the database objects of the standard, RPGMaster provided databases, indexed by name. |
'
+ + 'fieldGroups | An object defining the groups of fields held in repeating tables on the Character Sheet and named in the fields object |
'
+ + 'spellsPerLevel | An object specifying the number of spells that can be memorised at each level by each class of spellcaster |
'
+ + 'specMU | An array of strings naming the standard specialist wizard classes for this RPG version |
'
+ + 'ordMU | An array of strings naming the standard ordinary wizard classes for this RPG version |
'
+ + 'wisdomSpells | An array holding the additional spell slots or points per level for high wisdom scores |
'
+ + 'raceToHitMods | An object of race toHit modifiers with various weapon types and super-types |
'
+ + 'rangedWeapMods | The standard range mods to the toHit roll for firing ranged weapons at Near, Point Blank, Short, Medium, Long and Far ranges for this RPG version |
'
+ + 'saveLevels | An object mapping class levels to the baseSaves table saving throw entries |
'
+ + 'baseSaves | An object holding for each base class an array of base saving throws with improvement by level progression mapped by saveLevels |
'
+ + 'classSaveMods | An object of class modifiers to the base saving throws |
'
+ + 'raceSaveMods | An object of race modifiers to the base saving throws |
'
+ +'
'
+ +'
3.2 Manage Character Sheet Tables
'
+ +'
Some data on Character Sheets is best represented in tables, made up of multiple rows of multiple fields. Some tables can also have multiple columns of rows, each column containing rows which in turn have multiple fields (in fact, each column is considered a table in itself). Having a structured set of functions to add to, find, read, update, and remove data in these tables is a useful function to have. the ChatSetAttr API from The Aaron provides an amount of such functionality, but the RPGMaster Library provides a full suite of management functions, based on the definition of a standard Table Object, with associated Methods. The mechanics of the Character Sheet table are then hidden from the author of the API, who can concentrate on other functionality.
'
+ +'
The Library consists of the Table Object, and the Methods. The mechanics of the Table Object are hidden from the API (but can be exposed & used if you know what you are doing and understand the structure of Character Sheet tables fully). The important aspects to know are the functions to get the table object from the character sheet, and the methods to manipulate the table object.
'
+ +'
Table Management Functions
'
+ + '
'
+ + '
tableObject = getTable(character,fieldGroupDef,column,tableObject,caseSensitive)
'
+ + '
Gets a complete table object from a character sheet. Also discovers all the valid default values for the table fields from the fields object. Takes the following parameters:
'
+ + '
'
+ + '- character: the character sheet object for the character sheet from which to get the table
'
+ + '- fieldGroupDef: an entry from the fieldGroups object (obtained in the RPGMap with getRPGMap() - see Section 3.1). One of fieldGroup.MELEE .DMG .RANGED .AMMO .WPROF .MI .SPELLS .POWERS .INHAND .QUIVER
'
+ + '- column: (optional) for tables that have multiple columns, this is the column number to obtain. Each column is recovered as a complete table in itself
'
+ + '- tableObj (optional) an existing table object that will be overwritten with the complete table obtained by this command
'
+ + '- caseSensitive (optional) a true/false flag which, if true, makes all matches with table and field names in the table case sensitive (default is false, i.e. not case sensitive)
'
+ + '
'
+ + '
tableObject = getTableField(character,tableObject,tableDef,attributeDef,column,defaultVal,caseSensitive)
'
+ + '
Gets all rows for one field of a table. Adds that to the table object passed as a parameter. Faster than obtaining the full table with getTable(), but should only be used for finding and reading data and not for writing or adding new data and especially not adding rows with the .addTableRow() method. Takes the following parameters:
'
+ + '
'
+ + '- character: the character sheet object for the character sheet from which to get the table
'
+ + '- tableObject: an existing table object to add the field to, or an empty object \'{}\' to create a new table object with just this one field
'
+ + '- tableDef: the table definition from the fields object obtained with the getRPGMap() function (see Section 3.1). This will be the entry \'fields.xxx_table\' that defines the character sheet repeating table name and the first row index for the table
'
+ + '- attributeDef: the table field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). E.g. The entry for fieldName will be \'fields.xxx_fieldName\' that defines the character sheet table field name and property (current or max)
'
+ + '- column: (optional) for tables that have multiple columns, this is the column number to obtain. Each column is recovered as a complete table in itself
'
+ + '- defaultVal: (optional) the default value to be given to this field if a row is blanked, or created without a value specified for this field. If not provided, it itself is defaulted to the default value provided for the field in the fields object obtained with getRPGMap()
'
+ + '- caseSensitive (optional) a true/false flag which, if true, makes all matches with table and field names in the table case sensitive (default is false, i.e. not case sensitive)
'
+ + '
'
+ + '
defaultValues = initValues(fieldGroupDef)
'
+ + '
Gets a new default values object for the table defined by the provided field group definition from the fieldGroup object from the RPGMap obtained with getRPGMap() (see Section 3.1). The default values are those set for the table fields in the fields object. The structure of the values object is values[field_name][field_property]. Takes the following parameter:
'
+ + '
'
+ + '- fieldGroupDef: an entry from the fieldGroups object (obtained in the RPGMap, see getRPGMap() in Section 3.1). One of fieldGroup.MELEE .DMG .RANGED .AMMO .WPROF .MI .SPELLS .POWERS .INHAND .QUIVER
'
+ + '
'
+ +'
Table Object Methods
'
+ + '
'
+ + '
value = tableObject.tableLookup(attributeDef,row,defaultValue,returnObj)
'
+ + '
Looks up the value stored in a specified field in the specified row of the table object. Can take an optional default value (which will override the default value for the field stored in the table object itself), and an optional returnObj parameter to determine what is returned (value or object). Takes the following parameters:
'
+ + '
'
+ + '- attributeDef: the table field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). For field fieldName,This will be the entry \'fields.xxx_fieldName\' that defines the character sheet table field name and property (current or max)
'
+ + '- row: the row number of the row to get the field value from. If the row number is beyond the current end of the table, will return a default value or < undefined >, depending on the value of the defaultValue parameter
'
+ + '- defaultValue: a value or true or false (absolute boolian values). Defaults to true. If the field requested does not exist or does not have a value: true (or not provided) returns the default value stored for that field in the table object; false returns < undefined >; any other value is returned instead of the default value stored for that field in the table object
'
+ + '- returnObj: an attributeDef or true or false (absolute boolean values). Defaults to false. false (or not provided) returns the value or default value of the requested field; true returns the field object from the table instead of the value; an attributeDef specifies a different property to return, e.g. current or max (uses only the property field of the attributeDef)
'
+ + '
'
+ + '
tableObject = tableObject.tableSet(attributeDef,row,value,caseSensitive)
'
+ + '
Sets the value of the specified table field in the specified row to be the value provided. tableObject is changed in-place. Takes the following parameters:
'
+ + '
'
+ + '- attributeDef: the table field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). For field fieldName, this will be the entry \'fields.xxx_fieldName\' that defines the character sheet table field name and property (current or max)
'
+ + '- row: the row number of the row to set the field value in. If the row number is beyond the current end of the table, will create a new object for that field and the row specified: WARNING: creating a new field in a row this way can have unpredictable results. It is better to use the addTableRow() method to add complete new rows or to define all the fields in an existing row
'
+ + '- value: the value to store in the specified field in the specified row of the table
'
+ + '- caseSensitive (optional) a true/false flag which, if true, makes all matches with table and field names in the table case sensitive (default is false, i.e. not case sensitive)
'
+ + '
'
+ + '
tableObject = tableObject.addTableRow(row,values)
'
+ + '
Either add a new row to a table object with the provided or default values, or replace a current row with the provided or default values. tableObject is changed in-place. Takes the following parameters:
'
+ + '
'
+ + '- row: the row number of the row to get the field value from. If the row number is beyond the current end of the table, will create all the fields in the Table Object, either with the values provided, or the default values
'
+ + '- values: a values object (optional), created using the initValues() table function, and modified as required with new values for the fields. If not provided, defaults to the default values for the table fields held by the Table Object itself (effectively blanking the row). See the description of the initValues() function for the structure of the values object
'
+ + '
'
+ +'
row = tableObject.tableFind(attributeDef,valToFind)
'
+ + '
Find the first row in the Table Object with an entry in the field defined by the attributeDef with the value of valToFind. If found, row will be a valid table row number; otherwise the method returns < undefined >. Takes the following parameters:
'
+ + '
'
+ + '- attributeDef: the table field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). For the field fieldName, this will be the entry \'fields.xxx_fieldName\' that defines the character sheet table field name and property (current or max) to search
'
+ + '- valToFind: the value to be searched for in the attributeDef field
'
+ + '- row: the row number of the first row on which a match occurs, or < undefined > if no match was found
'
+ + '
'
+ +'
3.3 Attribute Management
'
+ +'
Two functions that get and set attribute values on the character sheet:
'
+ +'
value = attrLookup( character, attributeDef, tableDef, row, column, caseSensitive, defaultValue );
'
+ +'
A function that can get the value of an attribute from a character sheet, either from a standard attribute, or from a repeating table. However: for table field values using the Table Management functions, objects and methods is prefered and may suffer from fewer issues in future. Takes the following parameters:
'
+ +'
'
+ + '- character: the character sheet object for the character sheet from which to get the value
'
+ + '- attributeDef: the attribute field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). For a field fieldName this will be the entry \'fields.fieldName\' that defines the character sheet attribute field name and property (current or max)
'
+ + '- tableDef: (optional) the table definition from the fields object obtained with the getRPGMap() function (see Section 3.1). This will be the entry \'fields.xxx_table\' that defines the character sheet repeating table name and the first row index for the table
'
+ + '- row: (optional) the row number of the row to get the field value from. If the row number is beyond the current end of the table, will return a default value or < undefined >, depending on the value of the defaultValue parameter
'
+ + '- column: (optional) for tables that have multiple columns, this is the column number from which to obtain the field value.
'
+ + '- caseSensitive (optional) a true/false flag which, if true, makes all matches with table and field names case sensitive (default is false, i.e. not case sensitive)
'
+ + '- defaultValue: (optional) a value or true or false (absolute boolian values). Defaults to true. If the field requested does not exist or does not have a value: true (or not provided) returns the default value stored for that field in the table object; false returns < undefined >; any other value is returned instead of the default value stored for that field in the fields object
'
+ +'
'
+ +'
attributeObj = setAttr( character, attributeDef, value, tableDef, row, column, caseSensitive );
'
+ +'
A function that sets the value held by an attribute on a character sheet. Can also set values in repeating tables on the character sheet. However: for table attributes it is highly recommended that the Table Management functions, objects and methods (see Section 3.2) are used to get and set repeating table field values, as this might suffer from fewer issues in the future. Takes for following parameters:
'
+ +'
'
+ + '- character: the character sheet object for the character sheet on which to set the value
'
+ + '- attributeDef: the attribute field definition from the fields object obtained with the getRPGMap() function (see Section 3.1). For field fieldName this will be the entry \'fields.fieldName\' that defines the character sheet attribute field name and property (current or max). If the attribute object does not exist on the character sheet (and is not a table field) it will be created
'
+ + '- value: the value to store in the specified attribute of the specified character sheet
'
+ + '- tableDef: (optional) the table definition from the fields object obtained with the getRPGMap() function (see Section 3.1). This will be the entry \'fields.xxx_table\' that defines the character sheet repeating table name and the first row index for the table
'
+ + '- row: (optional) the row number of the row to set the field value in. If the row number is beyond the current end of the table, the function will attempt to create the new row, and put the value in it
'
+ + '- column: (optional) for tables that have multiple columns, this is the column number in which to set the field value. If the column does not exist, the function will return < undefined >
'
+ + '- caseSensitive (optional) a true/false flag which, if true, makes all matches with table and field names case sensitive (default is false, i.e. not case sensitive)
'
+ + '- attributeObj: the function returns the attribute object found and in which the value has been set, or < undefined > if a table field or row does not exist
'
+ +'
'
+ +'
3.4 Database Management
'
+ +'
The RPGMaster series of APIs use a number of databases holding data about spells, powers, magic items, character classes, attack macros, and other aspects. These are held as objects within the game-version and character sheet-version specific RPGMaster Library, and can be supplemented by GM provided additional databases held in Roll20 character sheets. See the database help handouts distributed with the RPGMaster APIs for more information on each type of database.
'
+ +'
The RPGMaster Library provides a number of database management functions which can be used by APIs to manage the provided databases. These functions are described here.
'
+ +'
DBindex = getDBindex( forceUpdate )
'
+ +'
A function to build or get and return an index to all entries in the RPGMaster databases. This function must be called before any items in the databases are queried or acted upon with the other database management functions. Having this index (which is globally held in the system) speeds up database access considerably over relying on the Roll20 object management functions, and allows the APIs to seamlessly access items that might be in either internal object databases or held in external character sheet databases, and supports the prioritisation of user-defined database items over Library defined items. Takes one optional parameter:
'
+ +'
'
+ + '- forceUpdate: (optional) A boolean flag: if true, forces the global database index to be recreated from scratch. If false or not provided, only builds the index if it does not already exist (e.g. when the game session has just started and the APIs initialise)
'
+ +'
'
+ +'
dbItemObject = abilityLookup( rootDB, dbItemName, character, silent, default );
'
+ +'
A function to get an entry from a database. Uses the global DBindex internally to access the correct database entry directly, eliminating the speed of a Roll20 object search. The building of the index using getDBindex() will determine the priority order of the potential sources for database items: see that function description for details. However, if the item does not have an entry in the DBindex (i.e. is not in any currently loaded database), and if a character sheet object is passed as a parameter, this abilityLookup() function will also search the character sheet for a copy of the database item which might have previously been placed there by a getAbility() function call. This allows characters to have items that come from user-defined databases in one campaign that are carried with them to other campaigns which perhaps don\'t have the same user-defined databases loaded.
'
+ +'
Takes the following parameters:
'
+ +'
'
+ + '- rootDB: The root database name for the type of item being recovered. Will access indexes from any database name that starts with the rootDB name. Can be one of MU-Spells-DB, PR-Spells-DB, Powers-DB, MI-DB, Attacks-DB, Class-DB
'
+ + '- dbItemName: The name of the item being searched for. The following characters are ignored: \'-\', \'_\', \'space\'.
'
+ + '- character: (optional) the character sheet object for the character sheet for which the item is relevant, and which might hold any orphaned item that is not available in current databases.
'
+ + '- silent: (optional) a boolean value which, if true, will surpress any error message if the rootDB is invalid or the item cannot be found. False or not provided will result in error messages being returned.
'
+ + '- default: (optional) a boolean value which, if false, returns < undefined > for any database item object if the item is not found or other errors occur, or if true or not defined returns a default item with the following structure:
'
+ + '{name:\'-\',type:\'\',ct:\'0\',charge:\'uncharged\',cost:\'0\',body:\'This is a blank slot. Go search out something new to fill it up!\'}
'
+ + '- dbItemObject A database item object, of class AbilityObj, with structure:'
+ + '
class AbilityObj {
'
+ + ' constructor( dBname, abilityObj, ctObj, source ) {
'
+ + ' this.dB = dBname;
'
+ + ' this.obj = abilityObj;
'
+ + ' this.ct = ctObj;
'
+ + ' this.source = source;
'
+ + ' this.api = (abilityObj && abilityObj[1]) ? (abilityObj[1].body.trim()[0] == \'!\') : false;
'
+ + ' }
'
+ +'
'
+ +'
dbItemObject = getAbility( rootDB, dbItemName, character, silent )
'
+ +'
A special version of abilityLookup() that not only gets the requested database item from the databases, but also saves that item to the stated character sheet for later reference. All parameters are defined the same as those for AbilityLookup() above. The returned dbItemObject.dB object attribute always holds the name of the character sheet, so that after a call to getAbility(), the standard Roll20 syntax of `%{${dbItemObject.dB}|${dbItemName}}` will work to display the database item in the chat window, but the original source database information will be lost.
'
+ +'
'
+ +'
itemObject = setAbility( character, itemName, itemBody, actionBar )
'
+ +'
A function to set or update a database item or an ability macro in a character sheet (database items are stored as ability macros on a character sheet). Note: the API in-memory databases cannot be updated in this way. Only items and ability macros on character sheets can be created and updated. Takes the following parameters:
'
+ +'
'
+ + '- character: the character sheet object of the character sheet on which the item is to be stored or updated.
'
+ + '- dbItemName: The name of the item being set. The case of the name and the following characters will be saved as part of the name, but are ignored for indexing and matching of the item name to those already stored on the character sheet: \'-\', \'_\', \'space\'.
'
+ + '- dbItemBody: The content to store as the data item, which will be stored as a character sheet Ability Macro body. Can consist of any text that can be stored in an Ability Macro body
'
+ + '- actionBar: (optional) a boolean value which, if true, will set the "Show as Token Action" flag for the Ability Macro that represents the item. Default is false
'
+ + '- itemObject: the returned item object which represents the item just set. Has the same definition as dbItemObject defined for the abilityObject() function
'
+ +'
'
+ +'
errFlag = buildCSdb( dbFullName, dbObj, typeList, silent )
'
+ +'
A function to extract an API databse from memory into a Character Sheet Database representation, so that the GM can examine the standard items stored there. Note: the function does not re-index the databases, so the Character Sheet database representation so created will not actually be used to recover data from by the system. If use of the Character Sheet database is required, it will be necessary to run a getDBindex( true ) function to force an index update. Takes the following parameters:
'
+ +'
'
+ + '- dbFullName: the name of the database to be built, which should be one of the databases named in the dbNames object returned by the getRPGMap() function (see Section 3.1), but does not have to be
'
+ + '- dbObj: the database object in dbNames that is to be extracted to the Character Sheet database named dbFullName
'
+ + '- typeList: one of clTypeLists (for character classes), spTypeLists (for all types of spell or power), or miTypeLists (for all other items), which have been obtained using getRPGMap() (see Section 3.1)
'
+ + '- silent: (optional) a boolean value which, if true, will surpress any error messages. False or not provided will result in error messages being sent to chat. An error flag is always returned
'
+ + '- errFlag: a boolean value indicating if an error occurred.
'
+ +'
'
+ +'
checkCSdb( dbName );
'
+ +'
A function to check any character sheet database for completeness and accuracy. If the body texts of the item Ability Macros have been set up in accordance with the relevant database documentation handout, this function will ensure that all other attributes, lists and fields are set up to match the database item Ability Macros. Takes the following parameter:
'
+ +'
'
+ + '- dbName (optional) the name of the character sheet database to check. If not provided, or dbName = \'-db\', all character sheet databases will be checked
'
+ +'
'
+ +'
',
+ },
+ RPGCS_Setup: {name:'RPGMaster CharSheet Setup',
+ version:1.09,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGMaster CharSheet Setup v1.09'
+ +'
'
+ +''
+ +'
Character Sheet and Token setup for use with RPGMaster APIs
'
+ +'
1. Using APIs to do setup
'
+ +'
The simplest way to configure a Character Sheet for use with the RPGMaster APIs is to use the functions of the APIs to set up the Character Sheet. If the CommandMaster API is installed, a number of features and commands are provided to help the DM/Game Creator in this process.
'
+ +'
The most basic of these is to configure a blank Character Sheet.
'
+ +'
- Use the [+Add] button on the Roll20 Journal to add a new blank Character Sheet, and Roll20 displays a form to give the sheet a name (or accept with the default provided by Roll20) and optionally an image.
'
+ +'- Select the [Save Changes] button on this form, and then close the blank Character Sheet.
'
+ +'- Drag the newly created Character Sheet onto the map area of the Roll20 UI.
'
+ +'- Switch to the Chat Window, and the Review & Set Race & Classes menu has appeared (scroll down to the bottom if need be).
'
+ +'- If this menu has not appeared, the menu can be opened on the DM\'s Token-Setup button.
'
+ +'- Make sure the token you have just placed on the map area is selected (often it is not).
'
+ +'- Selecting a Creature type from the Creature drop-down list will automatically setup the Character Sheet and Token to work with the APIs as that creature, setting all necessary fields and setting the Token as the default token for the Character Sheet. At this point the token can immediately be used in play as that creature.
'
+ +'- Selecting a Race and/or Class & level for the Character Sheet will not do as much - the basics will be set, but'
+ +'
- the Character Attributes of Strength, Dexterity, Constitution, Intelligence, Wisdom and Charisma must be rolled for and added to the sheet manually
'
+ +'- the Token is not linked or set up, as many fields still need to have values set
'
+ +'- use the Token-Setup menu to add Character menu action buttons to the Character Sheet, which provide menu access for Players
'
+ +'- the DM\'s Token-Setup menu can be used to complete setting other aspects of the character before play
'
+ +'- if appropriate, once everything is set up manually make the token the default for the Character Sheet
'
+ +' - Use either the DM\'s Add-Items menu or the Character\'s Attk-Menu / Edit Weapons & Armour menu to add equipment including weapons & armour to Characters and even Creatures that can make use of them.
'
+ +'- Use the Character\'s Attk-Menu / Change Weapons menu to take weapons, shields, and other items in-hand, ready to use in attacks.
'
+ +'- Wizards and Priests can have spells added to their spell books on the DM\'s Token-Setup / Add to Spellbook menu. Then spells can be memorised from the spellbook using the Character\'s Spell-Menu / Memorise Spells menu.
'
+ +'- There are many other features of the APIs that can be used to enhance the Character / NPC being created with Powers, Magic Items and Proficiencies with weapons and Fighting Styles. Explore the other help handouts that come with the APIs for more information.
'
+ +'
Alternatively, the Character Sheet can be set up manually from scratch, or existing Characters with Character Sheets can be adapted for use with the APIs. This option is explored in the rest of this document. However, adding information (other than Character Attributes) to the Character Sheet manually will never be as functionally rich as using the APIs for setting up the sheet, and in some cases will restrict the operation of the APIs to not work in the optimal way. Always use the API menus where possible.
'
+ +'
'
+ +'
2. Token configuration
'
+ +'
The API can work with any Token configuration but requires tokens that are going to participate in API actions to represent a Character Sheet, so that actions relevant to the token and the character it represents can be selected.
'
+ +'
A single Character Sheet can have multiple Tokens representing it, and each of these are able to do individual actions made possible by the data on the Character Sheet jointly represented. However, if such multi-token Characters / NPCs / creatures are likely to encounter spells that will affect the Character Sheet (such as Haste and Slow) they must be split with each Token representing a separate Character Sheet, or else the one spell will affect all tokens associated with the Character Sheet, whether they were targeted or not! In fact, it is recommended that tokens and character sheets are 1-to-1 to keep things simple.
'
+ +'
The recommended Token Bar assignments for all APIs in the Master Series are:
'
+ +'
Bar1 (Green Circle): Armour Class (AC field) - only current value
'
+ +'Bar2 (Blue Circle): Base Thac0 (thac0-base field) before adjustments - only current value
'
+ +'Bar3 (Red Circle): Hit Points (HP field) - current & max
'
+ +'
It is recommended to use these assignments, and they are the bar assignments set by the CommandMaster API if its facilities are used to set up the tokens. However, the APIs will search for the most appropriate fields to use from the token and character sheet - only if the APIs can\'t find valid values will they revert to using these default fields on the token. All tokens must be set the same way, whatever way you eventually choose.
'
+ +'
These default assignments can be changed in each API, by changing the fields object near the top of the RPGMaster Library API script (note: \'bar#\' and \'value\' or \'max\' are separate entries in an array of 2 elements):
'
+ +'
fields.Token_AC: defines the token field for the AC value (normally [\'bar1\',\'value\'])
'
+ +'fields.Token_MaxAC: defines the token field for the AC max (normally [\'bar1\',\'max\'])
'
+ +'fields.Token_Thac0: defines the token field for the Thac0 value (normally [\'bar2\',\'value\'])
'
+ +'fields.Token_MaxThac0: defines the token field for the Thac0 max (normally [\'bar2\',\'max\'])
'
+ +'fields.Token_HP: defines the token field for the HP value (normally [\'bar3\',\'value\'])
'
+ +'fields.Token_MaxHP: defines the token field for the HP max (normally [\'bar3\',\'max\'])
'
+ +'
Alter the bar numbers appropriately or, if you are not wanting one or more of these assigned: leave the two elements of the array as [\'\',\'\']. The system will generally work fine with reassignment or no assignment, but not always, especially if Effect Macros are programmed with hard-coded field assignments rather than using ^^field-tag^^ redirects (see RoundMaster API documentation for information on Effect Macros).
'
+ +'
3. Use with various game system character sheets
'
+ +'
The latest version of the RPGMaster series APIs use various game and character sheet-specific versions the RPGMaster Library to implement the relevant rules, parameters and databases specific to a game-version and/or Roll20 character sheet version. Loading the correct RPGMaster Library will configure all the RPGMaster APIs to work with that game rule set and character sheet. However: at the time of writing, only the AD&D 2E game version, and Advanced D&D 2E Character Sheet by Peter B. are supported.
'
+ +'
4. Matching the API to a type of Character Sheet
'
+ +'
As with other game and character sheet specific configuration, selecting the correct RPGMaster Library will configure the RPGMaster APIs for the character sheet in use. If a character sheet does not have the fields specified in the Library, the RPGMaster APIs will create them - it can, in fact, work with a totally blank character sheet definition and it will create all of the fields it requires from scratch: it just won\'t look very pretty or be very usable as a character sheet! However, you can alter the Library to work with any character sheet as follows (though the game rules and databases will remain those coded in that version of the Library).
'
+ +'
The Library API has an object definition called \'fields\', which contains items of the form
'
+ +'
Internal_api_name: [sheet_field_name, field_attribute, optional_default_value, optional_set_with_worker_flag]
'
+ +'
A typical example might be:
'
+ +'
Fighter_level:[\'level-class1\',\'current\'],
'
+ +'Or
'
+ +'MUSpellNo_memable:[\'spell-level-castable\',\'current\',\'\',true],
'
+ +'
The internal_api_name must not be altered! Doing so will cause the system not to work. However, the sheet_field_name and field_attribute can be altered to match any character sheet.
'
+ +'
Table names are slightly different: always have an internal_api_name ending in \'_table\' and their definition specifies the repeating table name and the index of the starting row of the table or -1 for a static field as the 1st row.
'
+ +'
Internal_api_table: [sheet_repeating_table_name,starting_index]
'
+ +'
An example is:
'
+ +'
MW_table:[\'repeating_weapons\',0],
'
+ +'
The internal_api_table must not be altered! Doing so will cause the system not to work. However, the sheet_repeating_table_name and starting_index can be altered to match any character sheet.
'
+ +'
Each character sheet must have repeating tables to hold weapons, ammo and magic items, as well as other data (if it does not, or they are not the ones specified in the fields object, the APIs will create them). By default, melee weapons \'in hand\' are held in sections of the repeating_weapons table, melee weapon damage in the repeating_weapons-damage table, ranged weapons in the repeating_weapons2 table, ammo in the repeating_ammo table, and magic items are held in the repeating_potions table. The table management system provided by the API expands and writes to repeating attributes automatically, and the DM & Players do not need to worry about altering or updating any of these tables on the Character Sheet. If the Character Sheet does not have tables to display any specific table, the APIs will create the table and attach it to the sheet and will be able to use it, but the Players and DM will not see the content except through the API menus and dialogues.
'
+ +'
5. Character Attributes, Races, Classes and Levels
'
+ +'
Character Attributes of Strength, Dexterity, Constitution, Intelligence, Wisdom and Charisma are generally not directly important to the RPGMaster Series APIs, but the resulting bonuses and penalties are. All Attributes and resulting modifiers should be entered into the Character Sheet in the appropriate places (that is in the Character Sheet fields identified in the \'fields\' API object as noted in section 2 above).
'
+ +'
The Character\'s race is also important for calculating saves and ability to use certain items. The race should be set in the appropriate Character Sheet field. Currently, the races \'dwarf\', \'elf\', \'gnome\', \'halfelf\', \'halfling\', \'half-orc\' and \'human\' are implemented (not case sensitive, and spaces, hyphens and underscores are ignored). If not specified, human is assumed. The race impacts saves, some magic items and armour, and bonuses on some attacks.
'
+ +'
The system supports single-class and multi-class characters. Classes must be entered in the appropriate fields on the Character Sheet - if using the CommandMaster API, the --abilities or --class-menu commands can be used to set the classes and levels of characters and NPCs. Classes and levels affect spell casting ability, ability to do two-weapon attacks with or without penalty, and the ability to backstab and the related modifiers, among other things. Class and level also determine valid weapons, armour, shields, some magic items and saves.
'
+ +'
Important Note: the appropriate fields must be used for relevant classes - this varies by character sheet. E.g. on the Advanced D&D 2e Character Sheet, Fighter classes must be in the first class column, Wizard classes in the second column, Priest classes in the third, Rogues in the fourth, and Psions (or any others) in the fifth. If manually adding classes, it is important that these locations are adhered to.
'
+ +'
Note: classes of Fighter and Rogue (such as Rangers and Bards) that can use clerical &/or wizard spells will automatically be allowed to cast spells once they reach the appropriate level by the specific game version rules, but not before. They do not need to have levels set in the corresponding spell-caster columns - the casting ability & level is worked out by the system
'
+ +'
The Class-DB database holds definitions of the classes and class rules distributed with the system. If the MagicMaster API is loaded, use the !magic --extract-db Class-DB command to extract the database to a character sheet to examine and update the class rules. Examples of Classes currently supported are:
'
+ +'
Fighter classes | Wizard Classes | Priest Classes | Rogue Classes |
'
+ +'Warrior | Wizard | Priest | Rogue |
'
+ +'Fighter | Mage | Cleric | Thief |
'
+ +'Ranger | Abjurer | Druid | Bard |
'
+ +'Paladin | Conjurer | Healer | Assassin |
'
+ +'Beastmaster | Diviner | Priest of Life |
'
+ +'Barbarian | Enchanter | Priest of War |
'
+ +'Defender (Dwarven) | Illusionist | Priest of Light |
'
+ +' | Invoker | Priest of Knowledge |
'
+ +' | Necromancer | Shaman |
'
+ +' | Transmuter |
'
+ +'
The level for each class must be entered in the corresponding field. Multiple classes and levels can be entered, and will be dealt with accordingly. Generally, the most beneficial outcome for any combination will be used.
'
+ +'
6. Magic Items and Equipment
'
+ +'
All magic items and standard equipment, including weapons, armour, lanterns etc, are held in the Items table, which by default is set to the potions table, repeating_potions, on the Character Sheet. As with other fields, this can be changed in the \'fields\' object. The best way to put items into this table is by using the MagicMaster API commands --edit-mi or the GM-only command --gm-edit-mi. Alternatively, the AttackMaster --edit-weapons command can be used to load weapons, ammunition and armour into the Items table. It is generally possible to enter item names and quantities directly into the table and use them within the system, but only items that also exist in the supplied databases will actually work fully with the API (i.e. be recognised by the API as weapons, armour, ammo, etc). Other items can be in the table but will not otherwise be effective.
'
+ +'
Items can be added to the databases. See the Database Handouts for more information on the databases.
'
+ +'
7. Weapons and Ammo
'
+ +'
For the APIs to work fully the melee weapons, damage, ranged weapons and ammo must be selected using the AttackMaster --weapon command to take the weapon \'in hand\'. This will display a menu to take weapons and shields from the Items table and take them in hand, ready to use. This automatically fills all the correct fields for the weapons and ammo to make attacks, including many fields that are not displayed. Entering weapon data directly into the melee weapon, damage, ranged weapon and ammo tables will generally work, but will be overwritten if the --weapon command is used. Also, some API functions may not work as well or at all.
'
+ +'
For the InitiativeMaster API to support weapon attack actions weapon name, speed and number of attacks are the most important fields. For the AttackMaster API to support attack rolls, proficiency calculations, ranged attacks, strength and dexterity bonuses, and other aspects of functionality, fill in as many fields as are visible on the character sheet. When entering data manually, ensure that the row a melee or ranged weapon is in matches the row damage or ammo is entered in the respective tables (there is no need to do this if using AttackMaster functions to take weapons in-hand, as the relevant lines are otherwise linked).
'
+ +'
8. Weapon Proficiencies
'
+ +'
Weapon Proficiencies must be set on the Character Sheet. This is best done by using the CommandMaster API character sheet management functions, but can be done manually. Both specific weapons and related weapon groups can be entered in the table, and when a Player changes the character\'s weapons in-hand the table of proficiencies will be consulted to set the correct bonuses and penalties. Weapon specialisation and mastery (otherwise known as double specialisation) are supported by the CommandMaster functions, but can also be set by ticking/selecting the relevant fields on the Character Sheet weapon proficiencies table. If a weapon or its related weapon group does not appear in the list, it will be assumed to be not proficient.
'
+ +'
8. Spell books and memorisable spells
'
+ +'
The best (and easiest) way to give a Character or NPC spells and powers is to use CommandMaster API to add spells and powers to the Character\'s spellbooks, and MagicMaster API to memorise and cast spells and use powers. However, for the purposes of just doing initiative and selecting which spell to cast in the next round, the spells and powers can be entered manually onto the character sheet. Spells are held in the relevant section of the Spells table, which by default is set to the character sheet spells table, repeating_spells. As with other fields, this can be changed in the \'fields\' object. Note that on the Advanced D&D 2e character sheet Wizard spells, Priest spells & Powers are all stored in various parts of this one very large table.
'
+ +'
If you are just using the character sheet fields to type into, add spells (or powers) to the relevant "Spells Memorised" section (using the [+Add] buttons to add more as required) a complete row at a time (that is add columns before starting the next row). Enter the spell names into the "Spell Name" field, and "1" into each of the "current" & "maximum" "Cast Today" fields - the API suite counts down to zero on using a spell, so in order for a spell to appear as available (not greyed out) on the initiative menus, the "current" number left must be > 0. This makes spells consistent with other tables in the system (e.g. potion dose quantities also count down as they are consumed, etc).
'
+ +'
Then, you need to set the "Spell Slots" values on each level of spell to be correct for the level of caster. Just enter numbers into each of the "Level", "Misc." and "Wisdom" (for Priests) fields, and/or tick "Specialist" for the Wizard levels as relevant. This will determine the maximum number of spells memorised each day, that will appear in the spells Initiative Menu. Do the same for Powers using the "Powers Available" field. As with other fields on the character sheet, each of these fields can be re-mapped by altering the \'fields\' object in the RPGMaster Library API.
'
+ +'
Spells can only be cast if they have macros defined in the spell databases (see Spell Database Handout). If the CommandMaster API is loaded, the DM can use the tools provided there to manage Character, NPC & creature spell books and granted powers from the provided spell & power databases.
'
+ +'
The spells a spell caster can memorise (what they have in their spell books, or what their god has granted to them) is held as a list of spell names separated by vertical bars \'|\' in the character sheet attribute defined in fields.Spellbook (on the AD&D2E character sheet \'spellmem\') of each level of spell. On the AD&D2E sheet, the spell books are the large Spell Book text fields at the bottom of each spell level tab. The spell names used must be identical (though not case sensitive) to the spell ability macro names in the spell databases (hence the hyphens in the names). So, for example, a 1st level Wizard might have the following in their large Wizard Level 1 spell book field:
'
+ +'
Armour|Burning-Hands|Charm-Person|Comprehend-Languages|Detect-Magic|Feather-fall|Grease|Identify|Light|Magic-Missile|Read-Magic|Sleep
'
+ +'
Only these spells will be listed as ones they can memorise at level 1. When they learn new spells and put them in their spell book, this string can be added to just by typing into it. When they reach 3rd level and can have 2nd level spells, the following string might be put in the spell book on the Level 2 Wizard spells tab:
'
+ +'
Alter-Self|Invisibility|Melfs-Acid-Arrow|Mirror-Image|Ray-of-Enfeeblement
'
+ +'
Again, as they learn more spells and put them in their spell book, just edit the text to add the spells.
'
+ +'
Once these spell books are defined, the DM or Player can use the MagicMaster --mem-spell command (or an action button and associated ability macro on the Character Sheet) to memorise the correct number of these spells in any combination and store those on the Character Sheet.
'
+ +'
9. Powers
'
+ +'
Powers are defined in the Powers database - see Database handouts - though it is possible to use Wizard or Priest spells as powers. If the CommandMaster API is also loaded, the DM can use the tools provided there to manage Character, NPC & creature spellbooks and granted powers.
'
+ +'
Powers work in an almost identical way to Wizard & Priest spells, except that there is only 1 level of powers. Powers that the character has are added to the spell book on the Powers tab in the same way as spells, and then memorised using the --mem-spell command (which also works for powers with the right parameters). If you want to add Wizard or Priest spells as powers that can be used one or more times a day, or at will, the CommandMaster token setup spellbook function allows spells to be added to the powers spellbook. Otherwise, just add the name of the spell with a prefix of "MU-" or "PR-" manually to the powers spellbook e.g. to add a Wizard Light spell as a power, add it to the powers spellbook as "MU-Light". Spells added in this way can be memorised as powers in exactly the same way as other powers.
'
+ +'
',
+ },
+ WeaponDB_Handout: {name:'Weapon & Armour Database Help',
+ version:1.21,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Weapon & Armour Database Help v1.21'
+ +'
'
+ +''
+ +'
Weapon and Armour Databases
'
+ +'
for AttackMaster v'+version+' and later
'
+ +'
1. General Database information
'
+ +'
The RPGMaster APIs use a number of databases to hold Ability Macros defining weapons, ammo, and items of armour and their specifications, defined in the RPGMaster Library for various game versions. Previous versions of the RPGMaster series of APIs held their databases all externally as character sheets: from this version onwards this is not the case for databases supplied with the APIs, which are now held internally to the APIs. However, the AttackMaster or MagicMaster API command --extract-db can be used to extract any or all standard databases to Character Sheets for examination and update. DMs can add their own weapons, ammo and armour to additional databases held as Character Sheets. Additional databases should be named as follows:
'
+ +'
Weapons: | additional databases: MI-DB-Weapons-[added name] where [added name] can be replaced with anything you want. |
'
+ +'Ammo: | additional databases: MI-DB-Ammo-[added name] where [added name] can be replaced with anything you want. |
'
+ +'Armour: | additional databases: MI-DB-Armour-[added name] where [added name] can be replaced with anything you want. |
'
+ +'
However: 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.
'
+ +'
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.
'
+ +'
Important Note: all Character Sheet databases must have their \'ControlledBy\' value (found under the [Edit] button at the top right of each sheet) set to \'All Players\'. 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.
'
+ +'
Important Note: databases extracted using the --extract-db command will be able to be edited, but will also slow the system down - the versions held internally in the APIs are much faster for the system to access. Once any extracted database has been examined, it is best to delete them and use the --check-db to re-index the databases so the system operates as fast as possible.
'
+ +'
Each database has a similar structure, with:
'
+ +'
- Ability Macros named as the weapon, ammo or armour specified, and used to describe and provide specifications for using the commands with the AttackMaster API;
'
+ +'- Custom Attributes with the attribute name "ct-ability-macro-name", one per Ability Macro, which defines the speed and type for each item;
'
+ +'- An entry in a list on the character sheet in the spell book of the relevant Character Sheet tab (various spell books for different items - see entry below);
'
+ +'- Optionally, some entries come also with attributes that define Powers and Spells delivered by or stored on the item.
'
+ +'
Note: a DM only needs to program the Ability Macro using the formats shown in the next section, and then run the !attk --check-db or !magic --check-db command, which will correctly parse the ability macro and set the rest of the database entries as needed.
'
+ +'
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 ability macros - the RPGMaster Library provides several new Roll Templates that do not rely on any particular Character Sheet: RPGMweapon, RPGMammo, and RPGMarmour are the most relevant. See the RPGMaster Library help handout for further information. When a Player or an NPC or Monster views the specifications of a weapon, ammunition or piece of armour, 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.
'
+ +'
1.1 Replacing Provided Weapons
'
+ +'
If you want to replace any item 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.
'
+ +'
2. Weapon & Ammunition Databases
'
+ +'
Weapon databases are all character sheets that have names that start with MI-DB-Weapon (though in fact, weapons can be in any database starting with MI-DB- if desired), 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. Ammunition databases are similar, with the root database MI-DB-Ammo.
'
+ +'
As previously stated, each weapon definition has 3 (or 4) parts in the database (see Section 1): an Ability Macro with a name that is unique and matches the weapon, an Attribute with the name of the Ability Macro preceded by "ct-", a listing in the database character sheet of the ability macro name separated by \'|\' along with other weapons, and sometimes Attributes defining powers given by, or spells stored on the item. 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).
'
+ +'
Note: The DM creating new weapons does not need to worry about anything other than the Ability Macro in the database, as running the AttackMaster or MagicMaster -check-db MI-DB-Weapons command will update all other aspects of the database appropriately for all databases that have a name starting with or including \'MI-DB-Weapons\', as long as the Specs and Data fields are correctly defined. Use the parameter \'MI-DB-Ammo\' to check and update the ammunition databases. Running the command -check-db with no parameters will check and update all databases.
'
+ +'
Ability macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
Here are some examples:
'
+ +'
Longsword
'
+ +'
&{template:RPGMweapon}{{name=Longsword}} {{subtitle=Sword}}{{Speed=[[5]]}} {{Size=Medium}}{{Weapon=1-handed melee long-blade}}Specs=[Longsword,Melee,1H,Long-blade]{{To-hit=+0 + Str bonus}}ToHitData=[w:Longsword, sb:1, +:0, n:1, ch:20, cm:1, sz:M, ty:S, r:5, sp:5]{{Attacks=1 per round + level & specialisation, Slashing}}{{Damage=+0, vs SM:1d8, L:1d12, + Str bonus}}DmgData=[w:Longsword, sb:1, +:0, SM:1d8, L:1d12]{{desc=This is a normal sword. The blade is sharp and keen, but nothing special.}}
'
+ +'
The ability specification for this Longsword uses a Roll20 Roll Template, in this case defined in the RPGMaster Library (see the help handout for the Library to review the specifications of this template), but any Roll Template you desire can be used. The entries in the Roll Template itself can be anything you desire, giving as much or as little information as you want. However, the important elements for the APIs are those highlighted. Each of these elements are inserted between the elements of the Roll Template, meaning they will not be seen by the player when the macro is run. Generally spaces, hyphens and underscores in the data elements are ignored, and case is not significant. Each element is described below:
'
+ +'
Specs = [Type, Class, Handedness, Weapon Group]
'
+ +'
The Specs section describes what weapon type and proficiency groups this weapon belongs to. These fields must be in this order. This format is identical for all database items, whether in these databases or others used by the Master series of APIs.
'
+ +'
Type | is the type of the weapon, often the same as the ability macro name without magical plusses. |
'
+ +'Class | is one of Melee, Ranged, or Ammo (preceded by \'Innate-\' if the weapon does not require proficiency). |
'
+ +'Handedness | is #H, where # is the number of hands needed to wield the weapon. |
'
+ +'Weapon Group | is the group of related weapons that the weapon belongs to. |
'
+ +'
ToHitData = [w:Longsword, sb:1, +:0, n:1, ch:20, cm:1, sz:M, ty:S, r:5, sp:5]
'
+ +'
The ToHitData section specifies the data relating to an attack with the weapon. These fields can be in any order.
'
+ +'
w: | <text> the name to display for attacks with this weapon |
'
+ +'sb: | <0/1> strength bonus flag - specifies if the strength bonus is applicable to the To-Hit roll |
'
+ +'+: | <[+/-]#> the magical attack bonus/penalty - an integer of any size |
'
+ +'n: | <#[/#]> the basic number of attacks per round: the API will modify to account for specialisation and level |
'
+ +'ch: | <1-20> the roll for a Critical Hit, shown in the API with a green border to the attack AC achieved |
'
+ +'cm: | <1-20> the roll for a Critical Miss, shown in the API with a red border to the attack AC achieved |
'
+ +'sz: | the size of the weapon |
'
+ +'ty: | the type of damage done by the weapon - Slashing, Piercing and/or Bludgeoning |
'
+ +'sp: | <#> the speed of the weapon in segments |
'
+ +'r: | <[+/-/=]# [/#/#/#] > the range or range modifier of the weapon. Ranged weapons use PB / S / M / L |
'
+ +'
The number of attacks per round, n:, can be an integer or a fraction such as 3/2 meaning 3 attacks every 2 rounds. If using the InitMaster API the Tracker will have the correct number of entries for the Character relating to the number of attacks in the current round.
'
+ +'
The range for the weapon, r:, can be a single integer (representing the range of a melee weapon or simple ranged weapon) or a range modifier, starting with +, -, or =. The range modifier will amend the range of the ammo for a ranged weapon - ranged weapons vary their range with the ammo used. The weapon can use that range or modify it. Ranged weapon range modifiers can be of the form [[+/-]#/][+/-]#/[+/-]#/[+/-]# which will add or subtract a different modifier for each range ([Point Blank] / Short / Medium / Long - Point Blank range is optional)
'
+ +'
DmgData = [w:Longsword, sb:1, +:0, SM:1d8, L:1d12]
'
+ +'
The DmgData section specifies the data relating to the damage done by the weapon, and relates to melee weapons only (not ranged weapons). These fields can be in any order.
'
+ +'
w: | <text> the name to display for damage calculations for this weapon |
'
+ +'sb: | <0/1> strength bonus flag - specifies if the strength bonus is applicable to the Damage roll |
'
+ +'+: | <[+/-]#> the magical damage bonus/penalty - an integer of any size |
'
+ +'sm: | the base dice roll vs. small/medium creatures excluding any magical bonus |
'
+ +'l: | the base dice roll vs. large/huge creatures excluding any magical bonus |
'
+ +'
There are other optional fields that can be specified for To-Hit and/or Dmg data: see Section 4 below for complete details of all possible values.
'
+ +'
'
+ +'
Bastardsword+1
'
+ +'
&{template:RPGMweapon}{{name=Bastard Sword+1}}{{subtitle=Magic Sword}}{{Speed=[[5]]}}{{Size=Medium}}{{Weapon=1 or 2-handed melee long blade}}Specs=[Bastard-Sword,Melee,1H,Long-blade],[Bastard-Sword,Melee,2H,Long-blade]{{To-hit=+1 + Str Bonus}}ToHitData=[w:Bastard Sword+1, sb:1, +:1, n:1, ch:20, cm:1, sz:M, ty:S, r:5, sp:6,rc:uncharged],[w:Bastard Sword 2H+1, sb:1, +:1, n:1, ch:20, cm:1, sz:M, ty:S, r:5, sp:8,,rc:uncharged]{{Attacks=1 per round + specialisation & level, Slashing}}{{Damage=+1, 1-handed SM:1d8 L:1d12, 2-handed SM:2d4 L:2d8}}DmgData=[w:Bastard Sword+1,sb:1,+:1,SM:1d8,L:1d12],[w:Bastard Sword 2H+1,sb:1,+:1,SM:2d4,L:2d8]{{desc=This is a normal magical sword. The blade is sharp and keen, and is a +[[1]] magical weapon at all times.}}
'
+ +'
The Bastardsword can be used either single handed or two handed with different to-hit and damage outcomes. This can be represented in the macro as shown here, with multiple specification sections. When using the AttackMaster API !attk --weapon command to take the Bastardsword in hand, choosing 1 hand (either left or right) will use the 1-handed specifications, and choosing to take it in Both Hands will use the 2-handed specifications.
'
+ +'
All the field definitions are the same as for the Longsword example above, but there are (in this case) two sets of data for each section, the first set for 1-handed, the second set for 2-handed (as defined by the handedness entry in the Specs section data sets.
'
+ +'
'
+ +'
Longbow
'
+ +'
&{template:RPGMweapon}{{name=Longbow}}{{subtitle=Bow}}{{Speed=[[8]]}}{{Size=Medium}}{{Weapon=Ranged 2-handed Bow}}Specs=[Longbow,Ranged,2H,Bow]{{To-hit=+0 + Dex Bonus}}ToHitData=[w:Longbow,sb:0,db:1,+:0,n:2,ch:20,cm:1,sz:L,ty:P,sp:8]{{Attacks=Piercing, 2 per round}}{{desc=This is a normal longbow. The wood is polished, the string taut, but nothing special.}}
'
+ +'
A ranged weapon like a Longbow uses the same data section definitions as melee weapons except for the following additions and differences.
'
+ +'
ToHitData=[w:Longbow,sb:0,db:1,+:0,n:2,ch:20,cm:1,sz:L,ty:P,sp:8]
'
+ +'
The To-Hit section has an extra option:
'
+ +'
db: | <0/1> dexterity bonus flag - specifies if the dexterity bonus is applicable to the To-Hit roll. |
'
+ +'r: | the range data is not provided because this weapon does not modify the range of its ammo, but could be provided if required. |
'
+ +'
There is no DmgData section, as damage is defined by the ammo.
'
+ +'
'
+ +'
Shortbow of Targeting
'
+ +'
&{template:RPGMweapon}{{name=Shortbow of Targeting}}{{subtitle=Bow}}{{Speed=7/6/5/3}}{{Size=Medium}}{{Weapon=2-handed ranged bow }}Specs=[Shortbow,Ranged,2H,Bow],[Shortbow,Ranged,2H,Bow],[Shortbow,Ranged,2H,Bow],[Shortbow,Ranged,2H,Bow]{{To-hit=Dexterity bonus + 0 charges = normal bow
'
+ +'1 charge = +1 to hit
'
+ +'2 charges = +2 to hit
'
+ +'3 charges = +4 to hit}}ToHitData=[w:Shortbow +0,sb:0,db:1,+:0,n:2,ch:20,cm:1,sz:M,ty:P,sp:7,c:0,rc:recharging],[w:Shortbow +1,sb:0,db:1,+:1,n:2,ch:20,cm:1,sz:M,ty:P,sp:6,c:1,rc:recharging],[w:Shortbow +2,sb:0,db:1,+:2,n:2,ch:20,cm:1,sz:M,ty:P,sp:5,c:2,rc:recharging],[w:Shortbow +4,sb:0,db:1,+:4,n:2,ch:20,cm:1,sz:M,ty:P,sp:3,c:3,rc:recharging],{{Attacks=2 per round, no increases, Piercing}}{{desc=This shortbow has a charged magical targeting sight which incorporates a zoom dial. Increasing the zoom uses more magical charges, but improves the attack roll: 1 charge = +1, 2 charges = +2 and 3 charges = +4. Extra charges also speed up the bow as it is easier to draw the shot. The zoom can be returned to zero, and the bow shot as a notrmal shortbow.
'
+ +'Once all charges are expended, the bow continues to operate as a normal bow, and the charges will be regained after a long rest.}}
'
+ +'
This ranged weapon has magical capabilities which require charges to be expended, though it can be used as a normal weapon without expending any charges. The database definition uses the multiple attack specifications as per the Bastardsword above, but this time to create additional rows in the Attack menu with different attack speeds and damage values that use different charges.
'
+ +'
'
+ +'c: | # | The number of charges expended by an attack. Defaults to 1, and does not apply to uncharged items |
'
+ +'
'
+ +'
When shown in the Attack menu, any version of the weapon which requires more charges than it currently has will be gray, and will not be selectable for an attack.
'
+ +'
'
+ +'
Flight-Arrow+2 (Ammunition Database)
'
+ +'
&{template:RPGMammo}{{name=Flight Arrow+2}}{{subtitle=Magic Weapon}}{{Speed=As per bow}}{{Size=Small}}Specs=[Flight-Arrow,Ammo,1H,Arrow],[Flight-Arrow,Ammo,1H,Arrow]{{Ammo=+2,
'
+ +'**Warbow** vs. SM:1d8, L:1d8,
'
+ +'**Other Bows** vs. SM:1d6, L:1d6, Piercing}}AmmoData=[w:Flight Arrow+2, st:Bow, sb:1, +:2, SM:1d6, L:1d6],[w:Warbow Flight Arrow+2, t:warbow, sb:1, +:2, SM:1d8,L:1d8]{{Range=PB:30, others vary by bow
'
+ +'**Shortbow:**
'
+ +'S:50, M:100, L150,
'
+ +'**Longbow:**
'
+ +'S:60, M:120, L:210,
'
+ +'**Warbow:**
'
+ +'S90, M:160, L:250,
'
+ +'**Composite Sbow:**
'
+ +'S:50, M:100, L:180,
'
+ +'**Composite Lbow:**
'
+ +'S:70, M:140, L:210}}RangeData=[t:longbow, +:2, r:3/6/12/21],[t:shortbow, +:2, r:3/5/10/15],[t:warbow, +:2, r:3/9/16/25],[t:compositelongbow, +:2, r:3/7/14/21],[t:compositeshortbow, +:2, r:3/5/10/18]{{desc=A magical Flight Arrow of very fine quality}}
'
+ +'
Ammo has a different specification, as the To-Hit data sections are obviously part of the ranged weapon data. Instead it provides data on which weapons this can be ammo for, and what ranges it has for each. To determine this, it uses the weapon type and group-type set in the weapon Specs section.
'
+ +'
AmmoData=[w:Flight Arrow+2, st:Bow, sb:1, +:2, SM:1d6, L:1d6],[w:Warbow Flight Arrow+2, t:warbow, sb:1, +:2, SM:1d8,L:1d8]
'
+ +'
The AmmoData section is mostly the same as the DmgData sections (order of fields is immaterial and spaces, hyphens and underscores ignored in type and supertype names), but repeated data sets relate to the data for different types of weapon, and in addition:
'
+ +'
t: | the specific type of ranged weapon this data matches - takes priority over st:. An example is Longbow |
'
+ +'st: | the group-type of ranged weapon this data can be used for. An example is Bow, which means all bows |
'
+ +'
RangeData=[t:longbow, +:2, r:3/6/12/21],[t:shortbow, +:2, r:3/5/10/15],[t:warbow, +:2, r:3/9/16/25], [t:compositelongbow, +:2, r:3/7/14/21],[t:compositeshortbow, +:2, r:3/5/10/18],[st:bow, +:2, r:3/5/10/15]
'
+ +'
The RangeData section has one or more data sets relating to weapons that result in different ranges. The range specifications can have 3 or 4 parts: if 4, the first is for Point Blank range which is only relevant for specialists; the remaining 3 are always short, medium & long ranges. The ranges are normally specified as they are in the Player\'s Handbook, with 1 representing 10 etc. However, if the Short range is specified as 10 or greater, or the ranges are preceeded by \'=\' (e.g. r:=5/10/20), the ranges will be taken as literal and not multiplied by 10.
'
+ +'
Self-ammoed weapons e.g. Warhammer
'
+ +'
&{template:RPGMweapon}{{name=Warhammer}}{{subtitle=Hammer/Club}} {{Speed=[[4]]}}{{Size=Medium}}{{Weapon=1-handed melee or thrown club}}Specs=[Warhammer,Melee,1H,Clubs],[Warhammer,Ranged,1H,Clubs]{{To-hit=+0 + Str & Dex bonus}}ToHitData=[w:Warhammer, sb:1, +:0, n:1, ch:20, cm:1, sz:M, ty:B, r:5, sp:4],[ w:Warhammer, sb:1, db:1, +:0, n:1, ch:20, cm:1, sz:M, ty:B, sp:4]{{Attacks=1 per round + level & specialisation, Bludgeoning}}{{Damage=+0, vs SM:1d4+1, L:1d4, + Str bonus}}DmgData=[ w:Warhammer, sb:1, +:0, SM:1+1d4, L:1d4][]{{Ammo=+0, vs SM:1d4+1, L:1d4, + Str bonus}}AmmoData=[w:Warhammer,t:Warhammer,st:Throwing-club,sb:1,+:0,SM:1+1d4,L:1d4]{{Range=S:10, M:20, L:30}}RangeData=[t:Warhammer,+:0,r:1/2/3]{{desc=This is a normal warhammer. The blade is sharp and keen, but nothing special.}}
'
+ +'
A melee weapon that can also be thrown, and is its own ammunition, is termed a "self-ammoed" weapon. Its definition combines the data elements of both melee weapons, ranged weapons and ammunition.
'
+ +'
Specs=[Warhammer,Melee,1H,Clubs],[Warhammer,Ranged,1H,Clubs]
'
+ +'
Has two Specs data sets, one as a melee weapon and one as a ranged weapon.
'
+ +'
ToHitData=[w:Warhammer, sb:1, +:0, n:1, ch:20, cm:1, sz:M, ty:B, r:5, sp:4],[ w:Warhammer, sb:1, db:1, +:0, n:1, ch:20, cm:1, sz:M, ty:B, sp:4]
'
+ +'
ToHitData also has two sets of data, each of which relates to the corresponding Specs set.
'
+ +'
DmgData=[ w:Warhammer, sb:1, +:0, SM:1+1d4, L:1d4],[]
'
+ +'
DmgData does have two data sets, but the one corresponding to the ranged data is empty, as this data is in the Ammo data set.
'
+ +'
AmmoData=[w:Warhammer,t:Warhammer,st:Throwing-club,sb:1,+:0,SM:1+1d4,L:1d4]
'
+ +'
There is only 1 Ammo data set, as it only relates to the one weapon, itself.
'
+ +'
RangeData=[t:Warhammer,+:0,r:1/2/3]
'
+ +'
And only 1 Range data set, as it only relates to itself.
'
+ +'
Reusable, returning, breaking and modifying ammo
'
+ +'
Some ammunition (and also Self-ammoed weapons) behave differently to normal ammo when used: some breaks and cannot be retrieved (e.g. glass arrows), others magically return to the thrower\'s hand, and yet others change state when used (such as an unfolding net). These types of ammunition use the reuse attribute in their AmmoData section:
'
+ +'
'
+ +'ru: | [-]# | Defines the reusability or altering state of the ammunition |
'
+ +'
'
+ +'
The reuse attribute can take the following values:
'
+ +'
'
+ +'Value | Example | Description |
'
+ +'-2 | Staff-Spear | The ammunition and weapon will be deleted from all weapon tables when thrown as a ranged weapon, representing a non-returning magically charged thrown weapon, only recovered by using again as a magic item |
'
+ +'-1 | Glass Arrow | The ammunition will break on use, and is not recoverable |
'
+ +'0 | Flight Arrow | The default value. The ammunition will behave normally, reducing by 1 on use, and recoverable if the DM agrees |
'
+ +'1 | Whelm (magic Warhammer) | The ammunition quantity does not reduce with use. The ammo magically returns by itself |
'
+ +'2 | Spitting Snake Venoms | The ammunition is one of several possible for the weapon, but when one is used it becomes the only type available, not reducing, while the others all become 0 quantity |
'
+ +'3 | Net (Folded to Unfolded) | The ammunition has two or more states. The selected ammo will reduce by 1 and the other states will increase by 1 |
'
+ +'
'
+ +'
'
+ +'
Making a 1-Handed Weapon able to be 2-Handed
'
+ +'
Generally, it is not worth wielding the average 1-Handed weapon with both hands - you gain no advantage and lose use of the other hand. Clearly, there are some exceptions like a Basterd Sword which is designed to be used as either 1-handed or 2-handed and gains extra damage from doing so.
'
+ +'
However: certain 1-handed weapons gain benefits when a character has proficiency in the
Two-Hander Fighting Style, and perhaps with other (custom) fighting styles the DM chooses to set up. However, those without these proficiencies should not gain benefit from 2-handed use of these weapons. To achieve this outcome, these weapons need to be specified in a particular fashion in the Weapons Database. Here is an example:'
+ +'
Battle Axe
'
+ +'
&{template:RPGMweapon}{{name=Battle Axe}} {{subtitle=Axe}} {{Speed=[[7]]}} {{Size=Medium}} {{Weapon=1-handed melee axe}} Specs=[Battle-Axe,Melee,1H,Axe],[Battle-Axe,Melee,2H,Axe] {{To-hit=+0 + Str Bonus}} ToHitData=[w:Battle Axe,sb:1,+:0,n:1,ch:20,cm:1,sz:M,ty:S,r:5,sp:7,rc:uncharged] {{Attacks=1 per round + specialisation & level, Slashing}} {{Damage=+0, SM:1d8, L:1d12 + Str Bonus}} DmgData=[w:Battle Axe,sb:1,+:0,SM:1d8,L:1d12] {{desc=A standard Battle Axe of good quality, but nothing special}}
'
+ +'
Here it can be seen that there are two data sets specified for the Specs field and only one data set specified for the ToHitData. Doing this tells the APIs that this weapon can be taken in both hands, but generally will not gain any different advantages. If a Character is proficient or specialised in Two-Hander Fighting Style, however, the APIs will see that this is a 1-handed weapon held in both hands, and allocate it the correct benefits. But only certain weapons gain these benefits, so only certain weapons in the database should be set up this way.
'
+ +'
Artifact sword
'
+ +'
&{template:RPGMweapon}{{name=Jim the Sun Blade
'
+ +'Intelligent, Neutral}}{{subtitle=Magic Sword}}{{Speed=[[3]]}}WeapData=[w:Jim the Sun Blade,ns:5][cl:PW,w:Jims-Locate-Object,sp:100,lv:6,pd:1],[cl:PW,w:Jims-Find-Traps,sp:5,lv:6,pd:2],[cl:PW,w:Jims-Levitation,sp:2,lv:1,pd:3],[cl:PW,w:Jims-Sunlight,sp:3,lv:6,pd:1],[cl:PW,w:Jims-Fear,sp:4,lv:6,pd:2]{{Size=Special (feels like a Shortsword)}}{{Weapon=1 or 2 handed melee Long or Short blade}}Specs=[Bastard-sword|Short-sword,Melee,1H,Long-blade|Short-blade],[Bastard-sword|Short-sword,Melee,1H,Long-blade|Short-blade],[Bastard-sword,Melee,2H,Long-blade],[Bastard-sword,Melee,2H,Long-blade]{{To-hit=+2, +4 vs Evil + Str Bonus}}ToHitData=[w:Jim +2,sb:1,+:2,n:1,ch:20,cm:1,sz:M,ty:S,r:5,sp:3],[w:Jim vs Evil+4,sb:1,+:4,n:1,ch:20,cm:1,sz:M,ty:S,r:5,sp:3],[w:Jim 2H +2,sb:1,+:2,n:1,ch:20,cm:1,sz:M,ty:S,r:5,sp:3],[w:Jim 2H vs Evil+4,sb:1,+:4,n:1,ch:20,cm:1,sz:M,ty:S,r:5,sp:3]{{Attacks=1 per round}}{{Damage=+2, +4 vs Evil, + 1-handed SM:1d8 L:1d12, 2-handed SM:2d4 L:2d8}}DmgData=[w:Jim+2,sb:1,+:2,SM:1d8,L:1d12],[w:Jim vs Evil+4,sb:1,+:4,SM:2d4,L:2d8],[w:Jim 2H +2,sb:1,+:2,SM:1d8,L:1d12],[w:Jim 2H vs Evil+4,sb:1,+:4,SM:2d4,L:2d8]{{desc=An intelligent weapon: A Sun Blade called Jim (DMs Guide Page 185). It is Neutral. It needs its owner to be proficient with either a Short or Bastard Sword or promise to get such proficiency as soon as possible. It cannot be used by someone who is not proficient. It requires its owner to be Neutral on at least one of its axis, and may not be Evil. NG LN CN and of cause true N are all ok. Abilities:
'
+ +'**1:** It is +2 normally, or +4 against evil creatures, and does Bastard sword damage.
'
+ +'**2:** It feels and react as if it is a short sword and uses short sword striking time.
'
+ +'**3:** [Locate Object](!magic --mi-power @{selected|token_id}|Jims-Locate-Object|Jim-the-Sun-Blade|6) at [[6]]th Level in 120\' radius (1x day).
'
+ +'**4:** [Detect traps](!magic --mi-power @{selected|token_id}|Jims-Find-Traps|Jim-the-Sun-Blade|6) of large size in 10\' radius (2xday).
'
+ +'**5:** [Levitation](!magic --mi-power @{selected|token_id}|Jims-Levitation|Jim-the-Sun-Blade|1) 3x a day for 1 turn (cast at 1st Level).
'
+ +'**6:** [Sunlight](!magic --mi-power @{selected|token_id}|Jims-Sunlight|Jim-the-Sun-Blade|6) Once a day, upon command, the blade can be swung vigorously above the head, and it will shed a bright yellow radiance that is like full daylight. The radiance begins shining in a 10-foot radius around the sword-wielder, spreading outward at 5 feet per round for 10 rounds thereafter, creating a globe of light with a 60-foot radius. When the swinging stops, the radiance fades to a dim glow that persists for another turn before disappearing entirely.
'
+ +'**7:** It has a special purpose namely Defeat Evil.
'
+ +'**8:** On hitting an Evil being it causes [Fear](!magic --mi-power @{selected|token_id}|Jims-Fear|Jim-the-Sun-Blade|6) for 1d4 rounds (unless saving throw is made). It can do this **twice a day** when the wielder desires.
'
+ +'**9:** It speaks Common and its name is Jim. It will talk to the party.
'
+ +'**10:** It has an ego of 16 and is from Yorkshire.
'
+ +'**11:** It will insist on having a Neutral wielder. (See Intelligent weapons on page 187 in DMG).
'
+ +'**12:** If picked by a player, it will be keen to become the players main weapon.
'
+ +'**13:** If picked up by a player who is not Neutral it will do them 16 points of damage}}
'
+ +'
An artefact such as an intelligent sword with powers introduces data sets that specify the powers that the artefact has and how often they can be used. These match the API Buttons with calls to the MagicMaster API to enact the powers.
'
+ +'
WeapData=[w:Jim the Sun Blade,ns:5][cl:PW,w:Jims-Locate-Object,sp:100,lv:6,pd:1],[cl:PW,w:Jims-Find-Traps,sp:5,lv:6,pd:2],[cl:PW,w:Jims-Levitation,sp:2,lv:1,pd:3],[cl:PW,w:Jims-Sunlight,sp:3,lv:6,pd:1],[cl:PW,w:Jims-Fear,sp:4,lv:6,pd:2]
'
+ +'
The WeapData data sets can be used to define the powers that an artefact has (or stored spells - see MagicMaster API for more information on spell storing)
'
+ +'
1st data set:
'
+ +'
w: | <text> The name of the weapon (not currently used) |
'
+ +'ns: | <#> The number of spells or powers for which the specifications follow |
'
+ +'
Subsequent data sets:
'
+ +'
cl: | < MU / PR / PW > The type of data: MU=Wizard, PR=Priest, PW=Power |
'
+ +'w: | <text> Name of the spell or power: must be the same as the corresponding database definition |
'
+ +'sp: | <#> Speed of the spell/power casting in segments (1/10ths of a round) |
'
+ +'lv: | <#> The level at which the artefact will cast the spell/power (if omitted will use character\'s level) |
'
+ +'pd: | <-1 / #> Number per day, or -1 for "use at will" |
'
+ +'
Execute command when taking in-hand or sheathing a weapon
'
+ +'
&{template:RPGMwandSpell}{{title=Rod of Alertness}}Specs=[Rod of Alertness,Melee,1H,Clubs],[Rod of Alertness,Wand,1H,Conjuration-Summoning]{{splevel=Footman\'s Mace/Rod}}WeapData=[w:Rod of Alertness,wt:10,on:\\api;modattr --charid @{selected|character_id} --fb-public --fb-header @{selected|character_name} acts faster! --fb-content _CHARNAME_ improves their initiative rolls by 1 --init-mod|-1,off:\\api;modattr --charid @{selected|character_id} --fb-public --fb-header @{selected|character_name} acts more slowly --fb-content _CHARNAME_\'s initiative rolls return to normal --init-mod|+1 ]{{school=Conjuration/Summoning}}ToHitData=[w:Rod of Alertness,sb:1,+:1,n:1,ch:20,cm:1,sz:M,ty:B,r:5,sp:10,rc:uncharged]{{components=M}}DmgData=[w:Rod of Alertness,sb:1,+:1,SM:1+1d6,L:1d6]{{Time=[[10]]}}WandData=[w:Rod of Alertness,wt:10,sp:10,rc:uncharged,loc:left hand|right hand]{{range=Special}}{{duration=Special}}{{aoe=Special}}{{save=Special}}{{effects=This magical rod is indistinguishable from a footman\'s mace +1. It has eight flanges on its macelike head. The rod bestows +1 to the possessor\'s die roll for being *surprised*, and in combat the possessor gains -1 on initiative die rolls. If it is grasped firmly, the rod enables the character to ...
'
+ +'the rest of the specification of this item is not important here
'
+ +'
Another pair of attributes that can be included in the 1st WeapData data set specify simple commands to execute when the weapon is taken "in-hand" or "sheathed" using the Change Weapon menu. Only simple commands can be specified this way which do not include any multi-line commands or Roll20 macro calls (for more complex actions when taking in-hand or sheathing weapons, see the [Effects Database Help] for the "-inhand" and "-sheathed" event macros). The example above changes the wielder\'s initiative modifier by an improvement of 1 when the Rod of Alertness is taken in-hand, using the Chat Set Attr API !modattr command, and then reduces it back by 1 when the Rod is sheathed.
'
+ +'
on: | <command> | A simple command that can be expressed on a single line, executed when the weapon is taken "in-hand" using the Change Weapon menu |
'
+ +'off: | <command> | A simple command that can be expressed on a single line, executed when the weapon is "sheathed" (replaced with a different item) using the Change Weapon menu |
'
+ +'
'
+ +'
3. Armour Databases
'
+ +'
Armour databases are all character sheets that have names that start with MI-DB-Armour (as with weapons, this can be in any database starting with MI-DB- if desired), 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.
'
+ +'
As previously stated and as per the weapon and ammunition databases, each armour definition has 3 parts in the database (see Section 1): the Ability Macro, the ct- attribute, and the listing (and occasionally attributes for powers and spells). The quickest way to understand these entries is to examine existing entries. Do extract to the root databases and take a look (but remember to delete them after examination and use the --check-db command to re-index the databases).
'
+ +'
Note:The DM creating new armour entries does not need to worry about anything other than the Ability Macro in the database, as running the !attk --check-db MI-DB-Armour or !magic --check-db MI-DB-Armour command will update all other aspects of the database appropriately for all databases that have a name starting with or including \'MI-DB-Armour\', as long as the Specs and Data fields are correctly defined. Running the command -check-db with no parameters will check and update all databases.
'
+ +'
Here are some examples:
'
+ +'
Chain Mail
'
+ +'
&{template:RPGMarmour}{{name=Chain Mail}}{{subtitle=Armour}}{{Armour=Chain Mail}}Specs=[Chain Mail,Armour,0H,Mail]{{AC=[[5]] vs all attacks}}ACData=[a:Chain Mail,st:Mail,+:0,ac:5,sz:L,wt:40]{{Speed=[[0]]}}{{Size=Large}}{{Immunity=None}}{{Saves=No effect}}{{desc=This armor is made of interlocking metal rings. It is always worn with a layer of quilted fabric padding underneath to prevent painful chafing and to cushion the impact of blows. Several layers of mail are normally hung over vital areas. The links yield easily to blows, absorbing some of the shock. Most of the weight of this armor is carried on the shoulders and it is uncomfortable to wear for long periods of time.}}
'
+ +'
The ability specification for this suit of Chain Mail uses a Roll20 Roll Template, in this case defined by the loaded RPGMaster Library. The entries in the Roll Template itself can be anything you desire, giving as much or as little information as you want. However, the important elements for the AttackMaster API are those highlighted. Each of these elements are inserted between the elements of the Roll Template, meaning they will not be seen by the player when the macro is run. Generally spaces, hyphens and underscores in the data elements are ignored, and case is not significant. Each element is described below:
'
+ +'
Specs=[Chain Mail,Armour,0H,Mail]
'
+ +'
The Specs section of the specification has exactly the same format as for weapons and ammunition (and indeed all database items). See section 9 for the definition of the fields.
'
+ +'
Note:The armour Type (the 1st parameter) and Group-Type (the 4th parameter) are used to determine if the character is of a class that can use the armour. Currently implemented types are listed in Section 4.
'
+ +'
Note: Armour that fits on the body generally does not take any hands to hold, and so the third field, Handedness, is set to \'0H\'.
'
+ +'
ACData=[a:Chain Mail,st:Mail,+:0,ac:5,sz:L,wt:40]
'
+ +'
The Armour Class Data (ACData) section holds data specific to the armour. As with other data sections, fields can be in any order, and spaces, hyphens, underscores and case are ignored.
'
+ +'
a: | < text > the name of the armour to be displayed. Often the same as the Ability. |
'
+ +'st: | < group-type > the supertype of the armour, often the same as the fourth parameter of the Specs section. |
'
+ +'+: | <[+/-]#> the magical bonus or penalty of the armour (defaults to 0 if not supplied). |
'
+ +'ac: | <[-]#> the base armour class (excluding magical bonuses) for this type of armour. |
'
+ +'sz: | <[T/S/M/L/H]> The size of the item (not necessarily indicating its fit). |
'
+ +'wt: | <#> The weight of the item in lbs (could be considered kg - or any measure - if everything is the same). |
'
+ +'
Other possible fields are:
'
+ +'
t: | < armour-type > The specific armour type, often the same as the first parameter of the Specs section. |
'
+ +'db: | <[0/1]> A 1 means dexterity AC bonus combines with armour, 0 means armour prevents dexterity bonus from applying. |
'
+ +'+m: | <[-/+]#> The adjustment that the armour gives vs. missiles and ammunition of ranged weapons. |
'
+ +'+s: | <[-/+]#> The magical adjustment specifically against slashing damage. |
'
+ +'+p: | <[-/+]#> The magical adjustment specifically against piercing damage. |
'
+ +'+b: | <[-/+]#> The magical adjustment specifically against bludgeoning damage. |
'
+ +'rc: | Armour can be "cursed", but generally does not have charges. Default is "uncharged". See MagicMaster API documentation for more information on charges and curses. |
'
+ +'
'
+ +'
Shield+2
'
+ +'
&{template:RPGMarmour}{{name=Shield+2}}{{subtitle=Shield}}{{Shield=1-handed +2 Medium Shield made of wood & metal}}Specs=[Medium Shield,Shield,1H,Shields]{{AC=+[[2]] against all attacks from the front}}ACData=[a:Medium Shield+2, st:Shield, +:2,sz:M, wt:10] {{Speed=[[0]]}} {{Size=M}} {{Immunity=None}} {{Saves=No effect}} {{desc=All shields improve a character\'s Armor Class by 1 or more against a specified number of attacks. A shield is useful only to protect the front and flanks of the user. Attacks from the rear or rear flanks cannot be blocked by a shield (exception: a shield slung across the back does help defend against rear attacks). The reference to the size of the shield is relative to the size of the character. Thus, a human\'s small shield would have all the effects of a medium shield when used by a gnome.
'
+ +'*The medium shield* is carried on the forearm and gripped with the hand. Its weight prevents the character from using his shield hand for other purposes. With a medium shield, a character can protect against any frontal or flank attacks.}}
'
+ +'
As can be seen here, the specification for a Shield is almost identical in structure to that of any other armour, the major difference being in the Specs section type field.
'
+ +'
Note: The ac: field in the data section for a shield is always assumed to be \'+1\', meaning a shield adds 1 to the base AC before magical adjustments are taken into account. However, it can be specified as a different value, if desired.
'
+ +'
Note: All shields except a Buckler must be taken in hand using the !attk --weapon command before the Armour Class system of the AttackMaster API adds it to the AC for the character. A buckler is a special type of very small shield that is strapped to the arm and can counter only 1 blow per melee round, but allows both (all) hands to be free. In fact, any shield can have this functionality if desired, by setting the handedness field of the Specs section to be \'0H\', meaning it take no hands to hold it.
'
+ +'
'
+ +'
Armour-of-Vulnerability+-3
'
+ +'
&{template:RPGMarmour}{{name=Field Plate Armour of Vulnerability+/-3}}{{subtitle=Cursed Armour}}{{Armour=+/-3 selectively magical Field Plate}}Specs=[Armour-of-Vulnerability|Armour-of-Resistance,Armour,0H,Plate]{{AC=[[2]][[0-3]] better AC against Slashing damage'
+ +'+[[3]] worse AC against any other type}}ACData=[a:Armour-of-Vulnerability+-3,st:Mail,+S:3,+P:-3,+B:-3,ac:2,sz:L,wt:60,sp:0,rc:cursed]{{Speed=0}}{{Size=Large}}{{Immunity=None}}{{Saves=No effect}}{{desc=***Curse.*** This armor is cursed, a fact that is revealed only when an identify spell is cast on the armor or you attune to it. Attuning to the armor curses you until you are targeted by the remove curse spell or similar magic; removing the armor fails to end the curse. While cursed, you have vulnerability to two of the three damage types associated with the armor (not the one to which it grants resistance).}}{{desc1=This armour provides resistance to Slashing damage only, but vulnerability to Piercing and Bludgeoning damage.
'
+ +'This armor is a combination of chain or brigandine with metal plates (cuirass, epaulettes, elbow guards, gauntlets, tasets, and greaves) covering vital areas. The weight is distributed over the whole body and the whole thing is held together by buckles and straps. This is the most common form of heavy armor.
'
+ +'For each +1 bonus to armor, regardless of the type of armor, the wearer\'s Armor Class moves downward (toward AC 2 . . . to 1 . . . to 0, -1, -2, and so on). Note, however, that Armor Class can never be improved beyond -10}}
'
+ +'
This is a slightly more complex type of armour. It is a cursed item, and generally appears initially as Armour-of-Resistance+3, hence the Specs first parameter of armour type having two possible values, separated by \'|\'.
'
+ +'
The use of the damage type specific magical adjustment fields can be seen in the data section, along with the use of the rc: field tag with the value \'cursed\'. See section 4 for a complete list of rc: field values.
'
+ +'
'
+ +'
4. Specs & Data field values
'
+ +'
Below are lists of the current possible values for the item database Ability macro sections.
'
+ +'
4.1 Specs sections
'
+ +'
Specs=[Type, Item-Class, Handedness, Group-Type]
'
+ +'
4.1(a) Weapon Types
'
+ +'
There is an infinite list of weapon types: generally the type is the weapon name without any reference to magical plusses, so the Type of a Longsword+2 is Longsword. This Type is used to check for Proficiency.
'
+ +'
4.1(b) Weapon Item-Classes
'
+ +'
Melee | Melee weapon which strikes while in hand |
'
+ +'Ranged | Weapon that causes damage when thrown or with ammunition |
'
+ +'Innate-Melee or Innate-Ranged | Weapons that do not get a proficiency penalty. |
'
+ +'Ammo | Ammunition for a ranged weapon of a specific Type or Group-Type |
'
+ +'Magic | A magical attack from a magic item power or function |
'
+ +'
4.1(c) Weapon Handedness
'
+ +'
0H | A weapon that does not take a hand (e.g. spike on helm) |
'
+ +' 1H | A weapon that is 1-handed, such as a short sword |
'
+ +' 2H | A weapon that takes 2 hands to wield, such as a longbow |
'
+ +' 3H | A weapon that takes 3 hands... |
'
+ +' 4H | Etc (e.g. a siege weapon that needs 2 people to operate it) |
'
+ +' ... | ... |
'
+ +'
'
+ +'
4.1(d) Weapon Group-Types
'
+ +'
Weapon Group-Types determine related weapons for weapon proficiency, and whether it can be used by a Character of a specific class. The APIs use the definitions in the AD&D2e Fighter\'s Handbook section on \'Tight Groups\', extended to cover certain additional weapons and weapon types. Those implemented so far for the Weapon databases are:
'
+ +'
Arrow | Club | Great-Blade | Long-Blade | Short-Blade | Whip |
'
+ +'Axe | Crossbow | Hook | Medium-Blade | Sling |
'
+ +'Blowgun | Dart | Horeshoes | Pick | Spear |
'
+ +'Bow | Fencing-Blade | Innate | Polearm | Staff |
'
+ +'Bullet | Flail | Lance | Quarrel | Throwing-Blade |
'
+ +'
Types and Group-Types that can be used by various Character Classes are defined in the Class-DB class database for each class type:
'
+ +'
Warrior | Any |
'
+ +'Fighter | Any |
'
+ +'Ranger | Any |
'
+ +'Paladin | Any |
'
+ +'Beastmaster | Any |
'
+ +'Barbarian | Any |
'
+ +'Defender | "axe", "club", "flail", "long-blade", "fencing-blade", "medium-blade", "short-blade", "polearm" |
'
+ +'Wizard | (all types) "dagger", "staff", "dart", "knife", "sling" |
'
+ +'Priest / Cleric | "club", "mace", "hammer", "staff" |
'
+ +'Druid | "club", "sickle", "dart", "spear", "dagger", "scimitar", "sling", "staff" |
'
+ +'Healer | "club", "quarterstaff", "mancatcher", "sling" |
'
+ +'Priest of Life | "club", "quarterstaff", "mancatcher", "sling" |
'
+ +'Priest of War | Any |
'
+ +'Priest of Light | "dart", "javelin", "spear" |
'
+ +'Priest of Knowledge | "sling", "quarterstaff" |
'
+ +'Shaman | "long-blade", "medium-blade", "short--blade", "blowgun", "club", "staff", "shortbow", "horsebow", "hand-xbow" |
'
+ +'Rogue / Thief | "club", "short-blade", "dart", "hand-xbow", "lasso", "shortbow", "sling", "broadsword", "longsword", "staff" |
'
+ +'Bard | Any |
'
+ +'Assassin | Any |
'
+ +'
'
+ +'
4.1(e) Armour Types
'
+ +'
There is an infinite list of armour types: generally the type is the armour name without any reference to magical plusses, so the Type of Plate-Mail+2 is Plate-Mail. This Type is used to check for types of armour that can be worn by various classes.
'
+ +'
'
+ +'
4.1(f) Armour Item-Classes
'
+ +'
Armour | Any type of armour that does not need to be held to work |
'
+ +'Shield | A barrier that is held in hand(s) and defends against one or more attacks from the front |
---|
'
+ +'
'
+ +'
4.1(g) Armour Handedness
'
+ +'
0H Armour and Shields that are not held in the hand (e.g. a Buckler or a Helm)
'
+ +' 1H Generally a type of Shield that must be held in a hand
'
+ +' 2H Armour and Shields that use two hands, and/or prevent use of those hands for other things
'
+ +' 3H Generally siege engines that shield against attacks... (not yet implemented)
'
+ +' ... etc.
'
+ +'
'
+ +'
4.1(h) Armour Group-Types
'
+ +'
Armour Types and Group Types determine whether the armour can be used by various Character Classes. Restrictions are defined in the Class-DB classes database (see the relevant database handout):
'
+ +'
Warrior | Any |
'
+ +'Fighter | Any |
'
+ +'Ranger | Any |
'
+ +'Paladin | Any |
'
+ +'Beastmaster | Any |
'
+ +'Barbarian | "padded", "leather", "hide", "brigandine", "ring-mail", "scale-mail", "chain-mail", "shield", "ring", "magic-item","cloak" |
'
+ +'Defender | Any |
'
+ +'Wizard (all types) | "magic-item", "ring", "cloak" |
'
+ +'Priest / Cleric | Any |
'
+ +'Druid | "leather", "padded", "hide", "wooden-shield", "magic-item", "ring", "cloak" |
'
+ +'Healer | Any |
'
+ +'Priest of Life | Any |
'
+ +'Priest of War | Any |
'
+ +'Priest of Light | "studded-leather", "ring-mail", "chain-mail", "shield", "ring", "magic-item", "cloak" |
'
+ +'Priest of Knowledge | "magic-item", "ring", "cloak" |
'
+ +'Shaman | "padded", "leather", "hide", "brigandine", "ring-mail", "scale-mail", "chain-mail", "splint-mail", "banded-mail", "shield", "ring", "magic-item", "cloak" |
'
+ +'Rogue / Thief | Any |
'
+ +'Bard | "padded", "leather", "hide", "brigandine", "ring-mail", "scale-mail", "chain-mail", "ring", "magic-item", "cloak" |
'
+ +'Assassin | Any |
'
+ +'
'
+ +'
4.2 Data Sections
'
+ +'
'
+ +' '
+ +' '
+ +' Field | '
+ +' Format | '
+ +' Default Value | '
+ +' Description | '
+ +' Can be used in | '
+ +'
'
+ +' '
+ +' ToHit Data | '
+ +' Dmg Data | '
+ +' Ammo Data | '
+ +' Range Data | '
+ +' Weapon Data | '
+ +' AC Data | '
+ +'
'
+ +' '
+ +' w: | < text > | \'-\' | Name to be displayed | X | X | X | | | |
'
+ +' w: | < text > | \'-\' | Name of spell or power | | | | | X | |
'
+ +' a: | < text > | \'-\' | Name to be displayed | | | | | | X |
'
+ +' t: | < text > | \'\' | Type | | | X | X | | X |
'
+ +' st: | < text > | \'\' | Group Type (aka Tight-Group) | | | X | X | | X |
'
+ +' sb: | 0 / 1 | 0 | Strength Bonus | X | X | X | | | |
'
+ +' db: | 0 / 1 | 1 | Dexterity Bonus | X | | | | | X |
'
+ +' +: | [ + / - ] # | 0 | Magical adjustment | X | X | X | X | | X |
'
+ +' +m: | [ + / - ] # | 0 | Missile attack adjustment | | | | | | X |
'
+ +' +s: | [ + / - ] # | 0 | Slashing damage adjustment | | | | | | X |
'
+ +' +p: | [ + / - ] # | 0 | Piercing damage adjustment | | | | | | X |
'
+ +' +b: | [ + / - ] # | 0 | Bludgeoning damage adjustment | | | | | | X |
'
+ +' n: | # [ / # ] | 1 | Attacks per round | X | | | | | |
'
+ +' dp: | # | 0 | Dancing proficiency adjustment | X | | | | | |
'
+ +' ch: | 1 - 20 | 20 | Critical Hit roll value | X | | | | | |
'
+ +' cm: | 1 - 20 | 1 | Critical Miss roll value | X | | | | | |
'
+ +' sz: | [ t / s / m / l / h ] | \'\' | Size of item | X | | X | | | X |
'
+ +' r: | [# /] # / # / # | \'\' | Range | X | | | X | | |
'
+ +' r: | [+/-]# [ / [+/-]# / [+/-]# / [+/-]# ] | 0 | Range Modifier | X | | | | | |
'
+ +' ty: | SPB any combination | \'\' | Type of damage | X | | | | | |
'
+ +' sp: | [-]# | 0 | Speed in segments (1/10 round) | X | | | | X | |
'
+ +' c: | # | 1 | Charges used for attack (charged weapons only) | X | | | | | |
'
+ +' c: | # | 0 | Charges used if hit (charged weapons only) | | X | | | | |
'
+ +' pre: | 0 / 1 | 0 | Gets auto pre-Initiative attack | X | | | | | |
'
+ +' on: | < cmd > | \'\' | Cmd to execute when taken in-hand | | | | | X | |
'
+ +' off: | < cmd > | \'\' | Cmd to execute when sheathed | | | | | X | |
'
+ +' qty: | # | 0 | Maximum possible qty of Ammo | | | X | | | |
'
+ +' ru: | [-]# | 0 | Reusability of ammunition | | | X | | | |
'
+ +' sm: | dice roll format | 0 | Damage roll for Small & Medium opponents | | X | X | | | |
'
+ +' l: | dice roll format | 0 | Damage roll for Large & Huge opponents | | X | X | | | |
'
+ +' msg: | < text > | \'\' | Message to display with attk/dmg | X | X | X | | | |
'
+ +' ac: | [-]# | \'\' | Armour class | | | | | | X |
'
+ +' wt: | # | 1 | Weight of item in lbs | X | | | | | X |
'
+ +' ns: | # | 0 | Number of spells & powers defined for item | | | | | X | X |
'
+ +' cl: | MU / PR / PW | \'\' | Type of spell or power | | | | | X | |
'
+ +' pd: | -1 / # | 1 | Number per day (power only) | | | | | X | |
'
+ +' rc: | Charged / Uncharged / Rechargeable / Recharging / Self-charging / Cursed / Charged-Cursed / Recharging-Cursed / Self-charging-Cursed | Uncharged | Initial charged and Cursed status of item when found | X | | | | | X |
'
+ +' lv: | # | 1 | Level at which spell/power is cast | | | | | X | |
'
+ +' lv: | #:# | 1 | Min:Max level at which weapon/ammo can be used | X | | X | | | |
'
+ +' clv: | #:# | 1 | Min:Max caster level at which weapon/ammo can be used | X | | X | | | |
'
+ +' mulv: | #:# | 1 | Min:Max wizard level at which weapon/ammo can be used | X | | X | | | |
'
+ +' prlv: | #:# | 1 | Min:Max priest level at which weapon/ammo can be used | X | | X | | | |
'
+ +' pw: | Power | \' \' | Power cast by this attack (Magic class only) | X | | | | | |
'
+ +' desc: | < text > | \' \' | Power/spell/MI macro to display (Magic class only) | X | | | | | |
'
+ +' cmd: | < text > | \' \' | Command to send to chat (Magic class only) | X | | | | | |
'
+ +'
'
+ +'
'
+ +'
4.3 Character Sheet data fields
'
+ +'
As stated in section 7, the Character Sheet field mapping to the API script can be altered using the definition of the fields object. You can find the complete mapping for all APIs in the RPGMaster series, with an explanation of each, in a separate document.
'
+ +'
',
+ },
+ MagicDatabase_Help: {name:'Magic Database Help',
+ version:1.26,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Magic Database Help v1.26'
+ +'
'
+ +''
+ +'
Spell, Power & Magic Item Databases
'
+ +'
for MagicMaster v'+version+' and later
'
+ +'
1. General Database information
'
+ +'
The MagicMaster API uses a number of databases to hold Ability Macros defining spells, powers and magic items and their effects. The databases are distributed in the game-version-specific RPGMasther Library with many spell, power & magic item definitions. DMs can add their own weapons, ammo and armour to additional databases. Additional databases should be named as follows:
'
+ +'
'
+ +' Wizard Spells: | additional databases: MU-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Priest Spells: | additional databases: PR-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Powers: | additional databases: Powers-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Magic Items: | additional databases: MI-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +'
'
+ +'
However: 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.
'
+ +'
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.
'
+ +'
Important Note: all Character Sheet databases must have their \'ControlledBy\' value (found under the [Edit] button at the top right of each sheet) set to \'All Players\'. 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.
'
+ +'
Each Character Sheet database has a similar structure, with:
'
+ +'
'
+ +' - Ability Macros named as the spell, power or magic item specified, and used to describe and provide effects for spells, powers and magic items using the commands in the Magic Master API;
'
+ +' - 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;
'
+ +' - 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 Magic Items - see MI entry below).
'
+ +'
'
+ +'
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 spell, power and magic item ability macros. When a Player or an NPC or Creature views or casts a spell, power or uses a magic item the Magic Master API runs 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.
'
+ +'
When a Character, NPC or Creature views or uses an item, or views or casts a spell or power, the system searches the relevant databases for an item, spell or power with the selected name, and copies any database ability macro so found to the Character Sheet of the Character, NPC or Creature - if it already exists it will overwrite it with the latest version. If the system can\'t find a matching entry in any of the databases, API supplied or GM created, it then searches the Character Sheet for a matching ability macro previously saved there - this caters for the character/NPC/creature being moved to a new campaign that, for instance, does not hold a particular GM-created database item, as the macros the Character Sheet needs are always held on it.
'
+ +'
Whenever a new gameplay session is started, or the --check-db command is run, the system indexes all database items, both those in API memory and those held in Character Sheet databases: Character Sheet database items in user-defined databases take preference over API databases extracted to Character Sheet databases, which in turn take preference over API databases held in memory. This index speeds up access to the database items. However, items in Character Sheet databases are still much slower for the system to access than items in the API databases in memory. Thus it is best not to use extracted API databases in live gameplay, but only for copying items to support development of GM-created items in a GM\'s own databases. After use, the extracted API databases can just be deleted.
'
+ +'
1.1 Replacing Spells & Items
'
+ +'
If you want to replace any spell or item 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.
'
+ +'
'
+ +'
2. Spells and Powers Databases
'
+ +'
Spells/Powers databases have names that start with
'
+ +'
Wizard Spells: MU-Spells-DB-[added name]
'
+ +' Priest Spells: PR-Spells-DB-[added name]
'
+ +' Powers: Powers-DB-[added name]
'
+ +'
Those with version numbers of the form v#.# as part of the name will be ignored.
'
+ +'
As previously stated, each spell or power definition has 3 parts in the database (see Section 1): an Ability Macro with a name that is unique and matches the spell or power, an 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 others of the same level in the spell book of the level of the spell or power. The quickest way to understand these entries is to examine existing entries. Do extract the root databases using the !magic --extract-db command, and take a look (but remember to delete it after viewing to speed things up, and then reindex the databases using !magic --check-db)
'
+ +'
Note: The DM creating new spells and powers does not need to worry about anything other than the Ability Macro in the database, as running the command --check-db will update all other aspects of the database appropriately for all databases, as long as the Specs and Data fields are correctly defined. Use the name of the particular database as a parameter to check and update just that database. Running the command --check-db with no parameters will check and update all databases.
'
+ +'
Ability macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
2.1 Simple Spells
'
+ +'
The Ability Macro for a spell may look something like this:
'
+ +'
Sleep
'
+ +'
&{template:RPGMspell}{{title=@{selected|casting-name} casts Sleep as a level @{selected|casting-level} caster}}{{splevel=Level 1 Wizard}}{{school=Enchantment/Charm}}Specs=[Sleep,MUspellL1,1H,Enchantment-Charm]{{range=90 ft}}{{components=V, S, M}}{{duration=[[5*({10,@{selected|casting-level}}kl1)]] Rounds}}{{time=1}}{{aoe=[30ft Cube](!rounds --aoe @{selected|token_id}|square|feet|90|30||dark)}}{{save=None}}{{damage=[Sleep them](!rounds --target area|@{selected|token_id}|@{target|Select who to sleep|token_id}|Sleep|[[5*({10,@{selected|casting-level}}kl1)]]|-1|Snoring away, shake to awaken|sleepy)}}SpellData=[w:Sleep,lv:1,sp:1,gp:0.01,cs:VSM]{{effects=Up to [2d4](!\
\/r 2d4) Hit Dice of creatures with 4 HD or less are put to sleep beginning with the lowest HD creatures in the Area of Effect.}}{{materials=a pinch of fine sand, rose petals, or a live cricket.}}
'
+ +'
The ability specification for this Sleep spell uses a Roll20 Roll Template, in this case provided by the RPGMaster Library (see the documentation for the RPGMaster Library for specifications of this Roll Template), but any Roll Template you desire can be used. The entries in the Roll Template itself can be anything you desire, giving as much or as little information as you want. However, the important elements for the MagicMaster API are those highlighted. In red, two API buttons grant the player access to run RoundMaster API commands to show the Area of Effect of the spell, and then to mark affected tokens with a "Sleepy" status.
'
+ +'Each of the elements important to the database are inserted between the elements of the Roll Template, meaning they will not be seen by the player when the macro is run. Generally spaces, hyphens and underscores in the data elements are ignored, and case is not significant. Each element is described below:'
+ +'
Specs = [Type, Class, Handedness, Spell School]
'
+ +'
The Specs section describes what spell type and school this spell belongs to. These fields must be in this order. This format is identical for all database items, whether in these databases or others used by the Master series of APIs. Where there are multiple answers for a field, separate each by \'|\'. Note: Only A-Z, a-z, 0-9, hyphen/minus(-), plus(+), equals(=) point(.) and vertical bar(|) are allowed. Replace any forward slash with hyphen.
'
+ +'
'
+ +' Type | the type of the spell, often the same as the ability macro name. |
'
+ +' Class | one of MUSpellL#, PRSpellL#, or Power, where # is replaced by the spell level number. |
'
+ +' Handedness | #H, where # is the number of hands needed to cast the spell - i.e. does it have a somatic component. |
'
+ +' Spell School | the group of related spells that the spell belongs to. |
'
+ +'
'
+ +'
SpellData=[w:Sleep,lv:1,sp:1,gp:1,cs:VSM]
'
+ +'
The SpellData section specifies the data relating to the use of the spell. These fields can be in any order.
'
+ +'
'
+ +' w: | <text> | the name of the spell |
'
+ +' sph: | <text> | the sphere of a priest spell (not used for wizard spells) |
'
+ +' lv: | <#> | the level of the spell |
'
+ +' sp: | <[-]# or dice roll spec> | the casting time in segments for the spell. Can be >10 e.g. 20 for 2 rounds, or negative, or even a dice roll |
'
+ +' gp: | <#[.#]> | the cost of the material components of the spell in GP: fractions converted to SP & CP |
'
+ +' cs: | <VSM> | the component of the spell (Verbal, Somatic, Material) - can be any combination |
'
+ +'
'
+ +'
The casting time (or speed) sp: can be negative, meaning it gives a negative modifier to individual initiative (if InitMaster API is being used). It can also be greater than 10 segments, meaning it takes longer than 1 Round to cast. Multiply the number of Rounds it will take to cast by 10, or the number of Turns it will take to cast by 100 (if using the InitMaster API the rounds will be automatically counted down and the spell actually cast in the appropriate round, unless the casting is interrupted). It can also be a dice roll specification, which will be rolled at the point that a character selects the spell, power or item to use in a particular round, which means the speed can vary from round to round. E.g. under AD&D2e rules, potions are always of this nature (see the AD&D2e DMG p141).
'
+ +'
The cost of material components, gp:, is deducted from the Caster\'s money on their Character Sheet each time the spell is cast. The GM is informed of the spell being cast, by whom, and how much money it cost and how much money the Caster has left for each casting.
'
+ +'
The components of the spell, cs:, is currently not used and is for future expansion capabilities.
'
+ +'
2.2 Spells that need "To Hit"
'
+ +'
A more complex spell that needs the caster to hit the target with an attack roll, also known as a weaponised spell, might look something like this:
'
+ +'
&{template:RPGMspell}{{title=@{selected|Casting-name} casts
'
+ +'Spiritual Hammer
as a level @{selected|Casting-Level} caster}}Specs=[Spiritual-Hammer,Innate-Melee|PRspellL2,1H,Evocation],[Spiritual-Hammer,Innate-Melee,1H,Clubs],[Spiritual-Hammer,Innate-Melee,1H,Clubs]{{splevel=Level 2 Priest}}ToHitData=[w:Spiritual Hammer+1,prlv:1:6,+:1,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:3],[w:Spiritual Hammer+2,prlv:7:12,+:2,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:2],[w:Spiritual Hammer+3,prlv:13,+:3,sb:0,n:1,ch:20,cm:1,sz:T,ty:B,sp:1]{{school=Invocation}}{{sphere=Combat}}DmgData=[w:Spiritual Hammer+1,sb:0,+:1,sm:1+1d4,l:1d4],[w:Spiritual Hammer+2,sb:0,+:2,sm:1+1d4,l:1d4],[w:Spiritual Hammer+3,sb:0,+:3,sm:1+1d4,l:1d4]{{components=V,S,M}}weapData=[on:\\api;rounds --target caster|@{selected|token_id}|Spiritual-Hammer|\\lbrak;\\lbrak;3+@{selected|Casting-Level}\\rbrak;\\rbrak;|-1|Magical weapon in direction facing requires concentration|archery-target,off:\api;!rounds --removetargetstatus @{selected|token_id}|Spiritual-Hmmer]{{time=[[5]]}}{{range=[[10*@{selected|Casting-Level}]] yards}}{{duration=[[3+@{selected|Casting-Level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p207}}{{damage=SM [1d4+1](!
/r 1d4+1) or L [1d4](!
/r 1d4) +[[{{(ceil(@{selected|Casting-Level}/6)),3}kl1}]]}}{{damagetype=Bludgeoning}}SpellData=[w:Spiritual-Hammer,lv:2,sp:5,gp:2,cs:VSM,sph:Combat]{{effects=Base Thac0 same as caster [[@{selected|thac0-base}]] without strength bonus plus magical plus of +[[{{(ceil(@{selected|Casting-Level}/6)),3}kl1}]]. Damage is plus magical bonus but no others.}}{{materials=A normal war hammer (cost 2gp) hurled towards opponent, which disappears as spell is cast.}}{{use=Take the Spiritual Hammer in-hand using the *Change Weapon* menu for the duration of the spell, and use it to attack opponents. It will disappear when the duration expires or you *Change Weapon* to another weapon.}}
'
+ +'
This spell definition combines the elements of spell database specification and those of a weapon specification. The Specs data now includes the Innate-Melee weapon classification as well as the spell type and level, and as well as the SpellData there are weapon ToHitData and DmgData entries. In addition to the explanation here, please refer to the Weapon and Armour Database Help for more information on these sections.
'
+ +'
In this case, there are multiple repeating datasets in each data section: there are three possible variants of the Spiritual Hammer depending on the caster\'s level. The version to be selected is determined using the level specification attribute in the ToHitData section, in this case using "prlv", but there are four alternatives:
'
+ +'
'
+ +' lv: | Min : Max | The minimum and maximum level of character (both optional) |
'
+ +' clv: | Min : Max | The minimum and maximum level of spell caster, class based on last spell cast (both optional) |
'
+ +' mulv: | Min : Max | The minimum and maximum level of wizard spell caster for this weapon (both optional) |
'
+ +' prlv: | Min : Max | The minimum and maximum level of priest spell caster for this weapon (both optional) |
'
+ +'
'
+ +'
In each case, the minimum and maximum are separated by a colon, and either can be left out meaning there is no minimum or no maximum. Wizard and Priest spell casters include those other classes that can cast those spells, at their particular level of spell casting compitence: e.g. a 10th level Ranger is a 2nd level Priest spell caster. If the appropriate value for the caster of the spell falls within the range specified, then that weapon dataset will result in creation of a line in the appropriate weapon tables.
'
+ +'
If a spell has these weapon datasets included, and is currently memorised, it will appear in the weapon lists on the Change Weapon menu. Also, if this spell is cast, the Change Weapon menu will appear automatically after the spell description in the Chat window, ready to take the spell "in-hand" as a weapon and attack with it. Whichever way the Change Weapon menu appears, choosing the spell as a weapon will always mark the spell as having been cast. The spell-weapon will remain in-hand until the weapon is changed or the !attk --blank-weapon command is used which might, for instance, be included in the custom attack macro template (e.g. for Chromatic Orb) or in a spell end-effect (e.g. as in the Spiritual-Hammer-end Effect macro).
'
+ +'
2.3 Simple Powers
'
+ +'
The Ability Macro for a Power may look something like this:
'
+ +'
Turn Undead
'
+ +'
&{template:RPGMspell}{{title=@{selected|token_name} attempts to Turn Undead as a level @{selected|pr-casting-level} @{selected|class3}}} {{splevel=Power}} {{school=Necromancy}}Specs=[Turn-Undead,Power,1H,Necromancy]{{components=V,S}}{{time=[[10]]}}{{range=0}}{{duration=Until broken}}{{aoe=Undead within line of sight}}{{save=See turning table}}{{reference=PHB p103}}{{damage=[Turn It](!rounds --target area|@{selected|token_id}|@{target|Select undead|token_id}|Turned|99|0|Turned undead, flee if free-willed, stand aside if controlled|screaming)}}SpellData=[w:Turn Undead, sp:10, cs:VS]{{effects=**Remember that Paladins turn as a Priest of 2 levels lower.**
'
+ +'Attempting to turn counts as an action, requiring one round and occurring during the character\'s turn in the initiative order (thus, the undead may get to act before the character can turn them). The mere presence of the character is not enough--a touch of drama from the character is important. Speech and gestures are important, so the character must have his hands free and be in a position to speak. However, turning is not like spellcasting and is not interrupted if the character is attacked during the attempt.
'
+ +'To resolve a turning attempt, look on Table 61. Cross-index the Hit Dice or type of the undead with the level of the character (two levels lower for a paladin). If there is a number listed, roll 1d20. If the number rolled is equal to or greater than that listed, the attempt is successful. If the letter "T" (for "turned") appears, the attempt is automatically successful without a die roll. If the letter "D" (for "dispel") is given, the turning utterly destroys the undead. A dash (--) means that a priest or paladin of that level cannot turn that type of undead. A successful turn or dispel affects 2d6 undead. If the undead are a mixed group, the lowest Hit Dice creatures are turned first.
'
+ +'Only one die is rolled regardless of the number of undead the character is attempting to turn in a given round. The result is read individually for each type of undead.}}{{material=The Priest\'s holy symbol}}
'
+ +'
Essentially, Powers are just Spells by another name, that can be cast multiple times per day, and are innate to the Character\'s class, or to a creature. The specification is, therefore, almost identical to a spell. In the author\'s campaigns, Powers do not consume material components and therefore do not cost money to use (except in rare circumstances) hence there being no gp: specification (it defaults to 0gp), but other DMs can add material costs for Powers if desired. Powers are all 1 level, hence no lv: specification.
'
+ +'
'
+ +'
3. Magic Item Databases
'
+ +'
Magic Item databases have names such as
'
+ +'
Magic Items: MI-DB-[added name]
'
+ +'
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.
'
+ +'
As previously stated and as for other magic, each magic item definition has 3 parts in the database (see Section 1): an Ability Macro with a name that is unique and identifies the magic item, an 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 others of the same magic item type, which is one of: Potion, Scroll, Rod/Stave/Wand, Weapon, Armour, Ring, Miscellaneous, and also DM Only magic items. The quickest way to understand these entries is to examine existing entries. Do extract a root database using the !magic --extract-db command and take a look (but remember to delete it after viewing to speed things up, and then reindex the databases using !magic --check-db)
'
+ +'
Note: The DM creating new magic items does not need to worry about anything other than the Ability Macro in the database, as running the command --check-db will update all other aspects of the database appropriately for all databases, as long as the Specs and Data fields are correctly defined. Use the name of the particular database as a parameter to check and update just that database. Running the command --check-db with no parameters will check and update all databases.
'
+ +'
Ability macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
3.1 Simple Magic Items
'
+ +'
The Ability Macro may look something like this:
'
+ +'
Oil-of-Etherealness
'
+ +'
&{template:RPGMpotion}{{title=Oil of Etherealness}} {{splevel=Oil}} {{school=Alteration}}Specs=[Oil of Etherealness,Potion,1H,Alteration]{{components=M}}{{time=[[3]] rounds after application}} PotionData=[sp:30,rc:charged]{{range=User}}{{duration=4+1d4 turns}} {{aoe=User}} {{save=None}} {{healing=[Become Ethereal](!rounds --target single|@{selected|token_id}|@{target|Select a target|token_id}|Oil-of-Etherealness|[[10*(4+1d4)]]|-1|Ethereal|Ninja-mask)}}{{effects=This potion is actually a light oil that is applied externally to clothes and exposed flesh, conferring etherealness. In the ethereal state, the individual can pass through solid objects in any direction - sideways, upward, downward - or to different planes. The individual cannot touch non-ethereal objects.
'
+ +'The oil takes effect three rounds after application, and it lasts for 4+1d4 turns unless removed with a weak acidic solution prior to the expiration of its normal effective duration. It can be applied to objects as well as creatures. One potion is sufficient to anoint a normal human and such gear as he typically carries (two or three weapons, garments, armor, shield, and miscellaneous gear). Ethereal individuals are invisible.}}{{materials=Oil}}
'
+ +'
There is one new field in the data section (in this case called the PotionData section):
'
+ +'
'
+ +' rc: | <MI-type> | the recharging/curse type of the magic item. |
'
+ +'
'
+ +'
All magic items have a recharging/curse type: for details, see the --gm-edit-mi command in the MagicMaster API help documentation, section 4.1. If not supplied for a magic item definition, it defaults to uncharged. Generally, items in the database are not cursed-, but can have their type changed to cursed or some recharging cursed type when the DM stores them in a container or gives them to a Character using the --gm-edit-mi command.
'
+ +'
3.2 More Complex Items
'
+ +'
Other magic items might use different structures, and be more complex:
'
+ +'
Ring of Human Influence
'
+ +'
&{template:RPGMring}{{name=Ring of Human Influence}}{{subtitle=Ring}}Specs=[Ring of Human Influence,Ring,1H,Enchantment-Charm]{{Speed=[[0]]}}RingData=[w:Ring of Human Influence,sp:3,rc:uncharged,loc:left finger|right finger,on:\\apisetattr --fb-from Magic Items --fb-header Ring of Human Influence - Put on --fb-content _CHARNAME_ chooses to put on the Ring of Human Influence and now has a Charisma of 18 vs Humans and Humanoids --name @{selected|character_name} --RoHI-chr|@{selected|charisma} --charisma|18,off:\\apiresetattr --fb-from Magic Items --fb-header Ring of Human Influence - Take off --fb-content _CHARNAME_ chooses to take off the ring and their Charisma returns to normal --name @{selected|character_name} --RoHI-chr --charisma|@{selected|RoHI-chr},ns:2],[cl:PW,w:Suggestion,sp:3,lv:12,pd:1],[cl:PW,w:MU-Charm-Person,sp:3,lv:12,pd:1]{{Size=Tiny}}{{Immunity=None}}{{desc=Has the effect of raising the wearer\'s Charisma to 18 on encounter reactions with humans and humanoids. The wearer can make a [*suggestion*](!magic --mi-power @{selected|token_id}|Suggestion|Ring-of-Human-Influence|12) to any human or humanoid (saving throw applies). The wearer can also [charm](!magic --mi-power @{selected|token_id}|Charm-Person|Ring-of-Human-Influence|12) up to 21 levels/Hit Dice of human/humanoids (saving throws apply) just as if he were using the wizard spell, *charm person*. The two latter uses of the ring are applicable but once per day. Suggestion or charm has an initiative penalty of +3.}}{{use=Putting on the ring using the Change Weapon function changes Charisma to 18, and taking it off returns Charisma to its previous value. If using InitiativeMaster Group or Individual Initiative, select Initiative for a Magic Item, then the Ring of Human Influence to get the right item speed. Cast the spells by Using the Ring as a Magic Item, then selecting the appropriate spell in the Effect description.}}
'
+ +'
Here, as well as having API buttons to implement powers, the RingData entry specifies commands to execute when the ring is put on using the Change Weapon menu, and another when it is taken off, as well as other aspects of the ring\'s power - but ignore everything after the "ns:" for now.
'
+ +'
'
+ +' on: | Command string | A simple, single line command to execute on wearing the ring |
'
+ +' off: | Command string | A simple, single line command to execute on taking off the ring |
'
+ +'
'
+ +'
Staff of Striking
'
+ +'
&{template:RPGMwand}{{name=Staff of Striking}}Specs=[Staff of Striking|Quarterstaff,Rod|Melee,1H,Staff],[Staff of Striking|Quaretstaff,Melee,1H,Staff],[Staff of Striking|Quarterstaff,Melee,1H,Staff],[Staff of Striking,Rod,1H,Conjuration-Summoning|Animal]{{subtitle=Staff}}ToHitData=[w:Staff of Striking 1 charge,sb:1,+:3,n:1,ch:20,cm:1,sz:M,ty:SPB,r:5,sp:4,c:1,rc:rechargeable],[w:Staff of Striking 2 charges,sb:1,+:3,n:1,ch:20,cm:1,sz:M,ty:SPB,r:5,sp:4,c:2,rc:rechargeable],[w:Staff of Striking 3 charges,sb:1,+:3,n:1,ch:20,cm:1,sz:M,ty:SPB,r:5,sp:4,c:3,rc:rechargeable]{{Speed=[[4]]}}WandData=[qty:19+1d6]{{Size=Medium}}{{Weapon=1-handed melee oaken staff}}{{To-hit=+3, +Str Bonus}}{{Attacks=1 per round, magically the most favourable weapon type}}{{Damage= SM: 1d6, L:1d6, 1 charge: +3, 2 charges: +6, 3 charges: +9}}DmgData=[w:Staff of Striking 1 charge,sb:1,+:3,SM:1d6,L:1d6],[w:Staff of Striking 2 charges,sb:1,+:6,SM:1d6,L:1d6],[w:Staff of Striking 3 charges,sb:1,+:9,SM:1d6,L:1d6]{{Use=Melee weapon attack as normal, selecting the appropriate plus, which will deduct the number of charges automatically.}}{{desc=This oaken staff is the equivalent of a +3 magical weapon. (If the weapon vs. armor type adjustment is used, the staff of striking is treated as the most favorable weapon type vs. any armor.) It causes 1d6+3 points of damage when a hit is scored. This expends a charge. If two charges are expended, bonus damage is doubled (1d6+6); if three charges are expended, bonus damage is tripled (1d6+9). No more than three charges can be expended per strike. The staff can be recharged.}}
'
+ +'
The Staff of Striking is a weapon that can do additional damage if more charges are expended. The database definition uses the multiple attack / damage fields (as specified and explained in the Weapon and Armour Database Help handout) which results in multiple entries for the weapon to appear in the weapons tables on the character sheet, and in the Attack menu. Each ToHitData definition has the \'c\' attribute to define how many charges are expended when that version of the weapon is used:
'
+ +'
'
+ +' c: | # | The number of charges expended when the respective attack is made. Applies only to weapons / magic items that have charges. If in ToHitData is deducted when an attack is made, or if in DmgData only applies if a hit is achieved & damage done. Defaults to 1 charge (ToHitData) or 0 (DmgData) if not specified. If this item is not a weapon and the c: is in the item Data specification, it determines how many charges are deducted when the item is used, defaulting to 1. |
'
+ +' qty: | # or <dice spec> | The default quantity of charges the item will start with when added by the GM to a container. Can be a dice roll specification, in which case the number will be determined randomly with a dice roll. The GM can optionally alter this number when storing the item. |
'
+ +'
'
+ +'
When shown in the Attack menu, any version of the weapon which requires more charges than it currently has will be gray, and will not be selectable for an attack.
'
+ +'
3.3 Magic Items that must be taken in-hand
'
+ +'
Some magic items, especially Rods, Staves and Wands, must be taken in-hand like a weapon in order for their abilities to become fully available to the character by making an Attack action. The Rod of Smiting described above is a weapon of this nature, but others might have magical attacks as well as, or instead of melee or ranged attacks. Here is an example of one such device:
'
+ +'
Wand of Frost
'
+ +'
&{template:RPGMwand}{{title=Wand of Frost}}WandData=[w:Wand of Frost,wt:1,sp:2,c:0,rc:rechargeable,loc:left hand|right hand]{{splevel=Wand}}{{school=Evocation}}Specs=[Wand of Frost,Magic|Wand,1H,Evocation],[Wand of Frost,Magic|Wand,1H,Evocation],[Wand of Frost,Magic|Wand,1H,Evocation]{{components=V,M}}{{time=[[2]]}}{{range=Special}}ToHitData=[w:Ice Storm,desc:MU-Ice-Storm,lv:6,sp:2,c:1],[w:Wall of Ice,desc:MU-Wall-of-Ice,lv:6,sp:2,c:1],[w:Cone of Cold,desc:PW-WoF-Cone-of-Cold,lv:6,sp:2,c:2]{{duration=Special}}{{aoe=Special}}{{save=Special}}{{effects=A *frost* wand can perform three functions that duplicate wizard spells:
'
+ +'• *Ice storm:* A silvery ray springs forth from the wand and an ice (or sleet) storm occurs up to 60 feet away from the wand holder. This function requires one charge.
'
+ +'• *Wall of ice:* The silvery ray forms a wall of ice, six inches thick, covering a 600-squarefoot area (10\' x 60\', 20\' x 30\', etc.). Its initiative modifier is +2, and it uses one charge.
'
+ +'• *Cone of cold:* White crystalline motes spray forth from the wand in a cone with a 60-foot length and a terminal diameter of 20 feet. The initiative modifier is +2, and the effect lasts just one second. The temperature is -100 degrees F., and damage is 6d6, treating all 1s rolled as 2s (6d6, 12-36). The cost is two charges per use. Saving throw vs. wands is applicable.
'
+ +'The wand can function once per round, and may be recharged.}}{{materials=Wand}}{{Use=Take the wand in-hand using the *Change Weapon* dialogue in order to use its powers with the *Attack* action}}
'
+ +'
This specification introduces a new item Specs class, "Magic", and one of a new range of ToHitData fields, "desc":
'
+ +'
'
+ +' Magic | | The associated entries in the ToHitData will specify a magical attack, rather than a melee or ranged attack. There will not be a matching DmgData specification |
'
+ +' desc: | \' \' | The name of an ability macro describing the magical attack - this is a power, wizard or priest spell, or a magic item (even possibly this magic item) which will be displayed to the player when this magical attack is used. |
'
+ +' lv: | <#> | The level at which the magic item casts any power or spell. The spell will have effects as if cast at this level when cast from the magic item. |
'
+ +'
'
+ +'
The power, spell or magic item name used with the desc: field tag will be searched for in all the appropriate databases. However, some exist in more than one context (e.g. Light is both a Wizard and a Priest spell). It is possible to specify where the specific description can be found by preceding the name with one of "PW-", "MU-", "PR-", or "MI-" for Power, Wizard spell, Priest spell, and Magic Item respectively. Specifying the type also speeds up the search.
'
+ +'
There are other field tags that can be used with a Magic class ToHitData specification:
'
+ +'
'
+ +' pw: | \' \' | The name of a magic item power (with limited uses per day) to use as a magical attack, specified as per Section 4.1 below |
'
+ +' msg: | \' \' | A message to display to the player when the magical attack is made, encoded with the standard and extended RPGMaster escape sequences |
'
+ +' cmd: | \' \' | An API command to be executed when the magical attack is made, encoded with the standard and extended RPGMaster escape sequences |
'
+ +'
'
+ +'
Generally speaking, the cmd: and msg: tags can be used together instead of a desc: if there is no equivalent spell or power to display and only a simple status, timer or effect results from the magical attack. The pw: tag operates in an almost identical way to desc: but decrements the "per day" uses for the named power/spell (specified in the item data specification - see Section 4.1 below) each time it is used, which refresh after a Long Rest.
'
+ +'
3.4 Hiding Magic Item Details
'
+ +'
Sometimes, GMs want Players to have to discover the properties of magic items through quests, spell use, trial and error, or paying a high-level wizard to identify them. This is not always the case, and some groups may prefer for some or all items to reveal their nature on first examination. The database specification of an item allows for both approaches. An example of how to define an item to make it easy to hide its details is
'
+ +'
Flask of Curses
'
+ +'
&{template:RPGMitem}{{title=Flask}}{{name= of Curses}}{{subtitle=Magic Item}}Specs=[Flask of Curses,Miscellaneous,1H,Alteration]{{Speed=[[3]]}}MiscData=[w:Flask of Curses,st:Flask,wt:1,sp:3,qty:1,rc:charged]{{Size=S}}{{Looks Like=An ordinary flask of some type, containing a little liquid of some unidentifyable sort}}{{Use=The GM will tell you what happens when you use this item}}{{desc=This item looks like an ordinary beaker, bottle, container, decanter, flask, or jug. It has magical properties, but detection will not reveal the nature of the flask of curses. It may contain a liquid or it may emit smoke. When the flask is first unstoppered, a curse of some sort will be visited upon the person or persons nearby. After that, it is harmless. The type of curse is up to the DM}}{{GM Info=Hide this as some other jug, flask or bottle, using the GM\'s *Add Items* menu, and set *Reveal* to *on use*. Invent an imaginative curse to enact! Suggestions include the reverse of the priest\'s bless spell. Typical curses found on scrolls are recommended for use here as well. Or perhaps a monster could appear and attack all creatures in sight.}}
'
+ +'
Four elements contribute to the "simple" approach to being able to hide the item details from the Player / Character:
'
+ +'
'
+ + '- The splitting of the title & name of the definition: title is always displayed, and name is only added to the title when hidden details are made displayable by the GM.
'
+ + '- The optional addition of the st: attribute in the MiscData specification, which specifies the name of the item displayed on buttons while details are hidden. If not specified, defaults to the item class.
'
+ + '- The addition of the Looks Like tag which marks text that replaces the description while details are hidden and until the GM reveals the details.
'
+ + '- The Hide item as other item function in the GM\'s Add Items dialog, which will be available for items that have the Looks Like tag, or for which the GM chooses another item to hide this one as.'
+ +'
'
+ +'
The key element is the inclusion of the Looks Like data tag in the definition of the item. If an item has this tag, the GM\'s Add Items dialog will have the Hide Item as Item button enabled to hide the item as either what the st: data attribute specifies or (if not specified) the item class in the Specs specification of the item. If a player character views or uses such a hidden item, they will see only the title and the Looks Like text and nothing else. The GM can either set the item to automatically reveal its "secrets" when the player character views the item, uses the item, or only when revealed manually by the GM. It is also possible for the GM to select to hide the item as a completely different item using the Add Items dialog. For full details see the --gm-edit-mi entry in the MagicMaster Help handout.
'
+ +'
'
+ +'
4. Magic Items with Powers or Spell-Storing
'
+ +'
Some magic items, especially artefacts and sentient items, can store spells and/or have powers similar to characters. MagicMaster supports magic items of this type to a degree, although there are inevitably exceptions that the DM will have to get creative in their development! These items use API buttons that call various MagicMaster commands to deliver their capabilities.
'
+ +'
First to note is that items that have powers and spells use spell slots in the owning character\'s character sheet. These spell slots should not be used by characters in your campaign. If they are, errors might occur. By default, on the AD&D2E character sheet the system uses Wizard Level 14 spell slots for magic item powers, and Wizard Level 15 spell slots for spell-storing magic items. As standard AD&D2E only has spells up to level 9 this generally works without causing problems.
'
+ +'
Next, in addition to the three standard elements of the Ability Macro, the \'ct-\' attribute and the listing, these items require a 4th element which specifies their powers and spells. These are:
'
+ +'
'
+ +' mi-muspells-[item-name]: | Wizard spells able to be stored in the magic item |
'
+ +' mi-prspells-[item-name]: | Priest spells able to be stored in the magic item |
'
+ +' mi-powers-[item-name]: | Powers able to be used by the magic item |
'
+ +'
'
+ +'
In each case the [item-name] is replaced by the Ability macro name (which is not case sensitive).
'
+ +'
Note: The DM creating new spell storing or power wielding magic items does not need to worry about anything other than the Ability Macro in the database, as running the command --check-db will update all other aspects of the database appropriately for all databases, as long as the Specs and Data fields are correctly defined. Use the name of the particular database as a parameter to check and update just that database. Running the command --check-db with no parameters will check and update all databases.
'
+ +'
When a spell-storing or power wielding magic item is added to a magic item bag or container using --edit-mi or --gm-edit-mi, these attributes are automatically added to the character sheet by the APIs and also they are parsed by the system and the spells and/or powers are created in the relevant spell books automatically. When such an item is found in a container by a character, or passed from character to character, all of the stored spells & powers are deleted from the old character and created in the new character. A character gaining such an item can use its spells and powers immediately.
'
+ +'
4.1 Powerful Magic Item
'
+ +'
Here is an example of a power wielding magic item:
'
+ +'
Ring-of-Shooting-Stars
'
+ +'
!setattr --silent --sel --casting-level|1 --casting-name|@{selected|token_name}\'s Ring of Shooting Stars
'
+ +'&{template:RPGMring}{{name=Ring of Shooting Stars}}{{subtitle=Ring}}Specs=[Ring of Shooting Stars,Ring,1H,Evocation]{{Speed=[[5]]}}RingData=[w:Ring of Shooting Stars,sp:5,rc:charged,ns:6], [cl:PW,w:MU-Dancing-Lights,sp:5,pd:12], [cl:PW,w:MU-Light,sp:5,pd:2], [cl:PW,w:RoSS-Ball-Lightning,sp:5,pd:1], [cl:PW,w:RoSS-Shooting-Stars,sp:5,pd:3], [cl:PW,w:Faerie-Fire,sp:5,pd:2], [cl:PW,w:RoSS-Spark-Shower,sp:5,pd:1] {{Size=Tiny}} {{Immunity=None}} {{Resistance=None}} {{Saves=None}} {{desc=This ring has two modes of operation - at night and underground - both of which work only in relative darkness.
'
+ +'***During night hours, under the open sky***, the shooting stars ring will perform the following functions:
'
+ +'- [*Dancing lights*](!magic --mi-power @{selected|token_id}|Dancing-Lights|Ring-of-Shooting-Stars|1) as spell (once per hour).
'
+ +'- [*Light*](!magic --mi-power @{selected|token_id}|Light|Ring-of-Shooting-Stars|1), as spell (twice per night), 120-foot range.
'
+ +'- [*Ball lightning*](!magic --mi-power @{selected|token_id}|RoSS-Ball-Lightning|Ring-of-Shooting-Stars|1), as power (once per night).
'
+ +'- [*Shooting stars*](!magic --mi-power @{selected|token_id}|RoSS-Shooting-Stars|Ring-of-Shooting-Stars|1), as power (special).
'
+ +'***Indoors at night, or underground***, the ring of shooting stars has the following properties:
'
+ +'[*Faerie fire*](!magic --mi-power @{selected|token_id}|PR-Faerie-Fire|Ring-of-Shooting-Stars|1) (twice per day) as spell
'
+ +'[*Spark shower*](!magic --mi-power @{selected|token_id}|RoSS-Spark-Shower|Ring-of-Shooting-Stars|1) (once per day) as power
'
+ +'Range, duration, and area of effect of functions are the minimum for the comparable spell unless otherwise stated. Casting time is 5}}
'
+ +'
Note that the ability macro starts with a call to the ChatSetAttr API to set the casting-level to 1 and the name of the caster to be \< Character-name \>\'s Ring of Shooting Stars. Not strictly necessary, but a nice cosmetic.
'
+ +'
The data section now includes repeating data sets, one for each of the powers that the item has:
'
+ +'
RingData=[w:Ring of Shooting Stars,sp:5,rc:charged,ns:6], [cl:PW,w:MU-Dancing-Lights,sp:5,pd:12], …
'
+ +'
The first data set is very similar to the standard magic item data, with the addition of the ns: field, and is then followed by a number of repeated data sets specifying each of the powers:
'
+ +'
'
+ +' ns: | <#> | The number of powers (or spells) that the item can wield or store |
'
+ +' cl: | <MU/PR/PW> | The type of the power/spell specification: PW=power, MU=wizard spell, PR=priest spell |
'
+ +' w: | <text> | The name of the power/spell - must be exactly the same as the database name (case ignored) optionally prefixed by a power type, one of \'PW-\', \'MU-\', \'PR-\', or \'MI-\' for Power, Wizard spell, Priest spell, or Magic Item |
'
+ +' sp: | <[-/+]# / dice roll spec> | The speed or casting time of the power/spell in segments |
'
+ +' pd: | <-1/#> | The available casts per day, or -1 for \'at will\' |
'
+ +'
'
+ +'
By running the --check-db command (see section 6 and the note above) these data sets are used to correctly set up the database with the powers wielded, so that when a Character receives this item, the Character also gains the powers to use through the item. If a power type prefix is included for one or more power name, the respective database is searched for a matching entry: thus a Wizard or Priest spell can be specified as a power without having to explicitly add a duplicate of it to a Powers Database. If no prefix is specified, the system will first search the Powers Databases (API-supplied and user-supplied) for a match and, if not found there, will then search the MU Spells Databases, the Priest Spells Databases, all Magic Items databases, and then the character sheet of the creature wielding the item power for a match, in that order. An error occurs if no matches are found anywhere.
'
+ +'
Note: if a Character picks up two Power-wielding items with exactly the same item name (i.e. two copies of the same item) the results are unpredictable. This is best avoided. The GM can use the --gm-edit-mi menu to rename one or both items with a unique name to differentiate them: see the MagicMaster API documentation for details.
'
+ +'
Feel free to just copy the specification for a Ring-of-Shooting-Stars in an extracted copy of the Rings database and save it to a new Ability Macro with a different name, and then alter the power names, speeds, and uses per day, as well as the API Button --mi-power commands and the other text, to form new power-wielding magic items. Also, the Ring does not have to have 6 powers - just remove or add one or more repeating data sets to reduce or increase the number of powers.
'
+ +'
4.2 Spell Storing Magic Item
'
+ +'
Here is an example of a spell-storing magic item:
'
+ +'
Ring-of-Spell-Storing-HHSLS
'
+ +'
&{template:RPGMring}{{name=Ring of Spell Storing with Haste x2, Slow, Light & Sleep}}{{subtitle=Ring}}Specs=[Ring of Spell Storing,Ring,1H,Conjuration-Summoning]{{Speed=[[5]] regardless of spell}}RingData=[w:Ring of Spell Storing HHSLS,sp:5,rc:uncharged,ns:5], [cl:MU,w:Haste,sp:5,lv:6], [cl:MU,w:Haste,sp:5,lv:6], [cl:MU,w:Slow,sp:5,lv:7], [cl:MU,w:Light,sp:5,lv:3], [cl:MU,w:Sleep,sp:5,lv:3] {{Size=Tiny}}{{Store spell=[Store Priest Spell](!magic --mem-spell MI-PR|@{selected|token_id})
'
+ +'[Store Wizard Spell](!magic --mem-spell MI-MU|@{selected|token_id})}}{{Cast spell=[View](!magic --view-spell mi-muspells|@{selected|token_id}) or [Cast](!magic --cast-spell MI|@{selected|token_id}) spells}}{{desc=A ring of spell storing contains 1d4+1 spells which the wearer can employ as if he were a spellcaster of the level required to use the stored spells. The class of spells contained within the ring is determined in the same fashion as the spells on scrolls (see "Scrolls"). The level of each spell is determined by rolling 1d6 (for priests) or 1d8 (for wizards). The number rolled is the level of the spell, as follows:
'
+ +'Priest: 1d6, if 6 is rolled, roll 1d4 instead.
'
+ +'Wizard: 1d8, if 8 is rolled, roll 1d6 instead.
'
+ +'Which spell type of any given level is contained by the ring is also randomly determined.
'
+ +'The ring empathically imparts to the wearer the names of its spells. Once spell class, level, and type are determined, the properties of the ring are fixed and unchangeable. Once a spell is cast from the ring, it can be restored only by a character of appropriate class and level of experience (i.e., a 12th-level wizard is needed to restore a 6th-level magical spell to the ring). Stored spells have a casting time of [[5]].}}
'
+ +'
This is a specific version of a Ring of Spell Storing as the spells stored are specified in the macro. Alternatively, a blank Ring of Spell Storing is provided in the API Rings database. It is possible to use the --gm-edit-mi command menu to select this blank ring and use the facilities provided by the menu to add spells to this blank ring, and then rename it to reflect what the GM wants the ring to be. Again, see the MagicMaster API documentation for details.
'
+ +'
The only new field in these data sets is:
'
+ +'
'
+ +' lv: | <#> | The level of the caster who cast the spell into the ring. The spell will have effects as if cast at this level when cast from the ring. |
'
+ +'
'
+ +'
The lv: field only specifies the level of the initial spell caster when the item is first found. Once owned and used, the level of the spell caster is recorded each time a spell is refreshed by casting into the item. As the item is then passed from one Character to another, or stored in a container and recovered later, the levels at which the spells were cast is retained. However, if the item is reloaded from the databases, or a duplicate of the item is placed by the DM and found by another character, that version of the item will have the spell caster levels from the database definitions. Note that if a single Character picks up two versions of exactly the same spell storing item (i.e. with the same item name) the results are unpredicable... The GM should use the --gm-edit-mi menu to rename one or both of the rings to give them unique names.
'
+ +'
4.3 Magic-Item-storing Items
'
+ +'
Some items can store other items, including magic items. When such an item is viewed, used or exchanged between containers and characters, a character sheet specifically for the MI-storing item is created, or found if already previously created. The very act of viewing or using the item will trigger the creation or selection - there is no need for the GM or Player to do so. An example of this is a Bag of Holding.
'
+ +'
Bag of Holding
'
+ +'
&{template:RPGMitem}{{name=Bag of Holding}}{{subtitle=Magic Item}}Specs=[Bag of Holding,Miscellaneous,1H,Alteration]{{Size=[[15]]/[[250]]lbs, 30cu.ft}}MiscData=[w:Bag of Holding,st:Bag,sp:0,rc:uncharged,bag:2],[cl:MI,w:Potion-of-Healing,qty:1],[cl:MI,w:Scroll of Protection vs Magic,qty:2]{{Access=Drag the *Bag of Holding* token onto the map and use your MI menu *Search* function (to retrieve stuff from it) or *Store* function (to put stuff in it)}}{{desc=As with other magical bags, this one appears to be a common cloth sack of about 2 feet by 4 feet size. The Bag of Holding opens into a nondimensional space, and its inside is larger than its outside dimensions. Regardless of what is put into this item, the bag always weighs a fixed amount. This weight, the bag\'s weight limit in contents, and its volume limit are 15 lbs. 250 lbs. 30 cu. ft.
'
+ +'If overloaded, or if sharp objects pierce it (from inside or outside), the bag will rupture and be ruined. The contents will be lost forever in the vortices of nilspace.}}
'
+ +'
The important attributes are:
'
+ +'
'
+ +' bag: | <#> | Identifies the item as generating an item character sheet. Up to # items can be defined as initially being held in the item sheet (default 0) |
'
+ +' cl: | \'MI\' | Subsequent data sets with class \'MI\' define items initially held in the item, and will be inserted in a newly created item sheet when first viewed or used |
'
+ +' w: | <text> | The name of the item to initially be stored in the item character sheet MI bag. Should be an item named in a database |
'
+ +' qty: | <#> | The initial quantity of this item to be stored in the item-holding item character sheet MI bag (default 1) |
'
+ +'
'
+ +'
And one additional new attribute:
'
+ +'
'
+ +' st: | \'\' | Defines the "Item Type" (or SuperType) to be displayed when a container is searched that has its properties set to only show the types of items contained. If not provided, defaults to the item class from the Specs definition |
'
+ +'
'
+ +'
Thus, the definition of the particular Bag of Holding defined above, when a character has it in their Items & Equipment and either views or uses the item, will result in a new separate character sheet being created, named "Bag of Holding" (same as the item), placed in the controlling Player\'s journal and marked as controlled by that player, and for one Potion of Healing and two Scrolls of Protection vs. Magic to be inserted automatically into the Bag of Holding, ready for the Character to find and use by dragging the bag onto the map from their Journal and Searching the Bag.
'
+ +'
Once the Bag is created, the existing items can be taken out into the Character\'s own items & equipment, or new ones placed in the bag, the bag passed from one Character to another or itself placed in a different container.
'
+ +'
It is recommended that, where a GM places multiple item-holding items in a campaign, such as multiple Bags of Holding, that the GM uses the functions of the [Add Items] menu to rename each with a different name in the original container to which they are placed and before each is viewed or used (i.e. before the item character sheet is created by the system) - perhaps naming each after some previous owner or its creator. This prevents confusion with multiple Character Sheets all with the same name (which Roll20 will allow, but can definately be confusing for the GM who will see them all even if players only see the ones they control).
'
+ +'
'
+ +'
5. Weapons (if using AttackMaster API)
'
+ +'
Weapons, magical or not, are special types of items in the Magic Items databases. If coded properly (in the same way as those in the MI-DB-Weapons database), they can be used with the AttackMaster API to implement fully automatic weapon management, the ability to hold weapons "in-hand" or sheathed, to have automatic ammo and range management for ranged weapons, automatic entry of weapons into the melee and/or ranged weapons tables, ready to make attacks with magical plusses and other specifications all set up, and support for dancing weapons (ones that can attack without being held by the Character), creatures with more than 2 hands, and 1-handed weapons, 2-handed weapons, and even weapons that need more than 2 hands!
'
+ +'
See the Weapon & Armour Database Help handout and AttackMaster API documentation for how Weapon definitions should be structured for use with the AttackMaster API, which are just a few additions to the standard definition of an item.
'
+ +'
'
+ +'
6. Armour & Shields
'
+ +'
Like weapons, armour and shields of all types (including magical armour like magical Bracers and Rings of Protection) can be coded to be used with the AttackMaster API to automatically calculate the appropriate AC for various scenarios (such as with & without Shield, from the back, if surprised, etc). This will take into account if the armour is valid for the character class, determine which is the best armour combination that the character has, if various armour elements can or can\'t work together, and add in Dexterity bonuses or impairments. It will also allow magical effects cast on the character to take effect or be adjusted via the token "circles" and highlight when such an effect is in place by showing the relevant token bar (only when there is a difference between the token AC and calculated AC).
'
+ +'
See the Weapon & Armour Database Help handout and AttackMaster API documentation for how Armour & Shield definitions should be structured for use with the AttackMaster API, which are just a few additions to the standard definition of an item.
'
+ +'
Also, see the RoundMaster API documentation for how magical effects can be placed on and affect tokens and characters.
'
+ +'
'
+ +'
7. Specs & Data field values
'
+ +'
Below are lists of the current possible values for the item database Ability macro sections.
'
+ +'
7.1 Specs sections
'
+ +'
Specs=[Type, Item-Class, Handedness, Group-Type]
'
+ +'
There are no default settings for any of the Specs data fields. All must be explicitly specified.
'
+ +'
7.1(a) Spell Types
'
+ +'
There is an infinite list of spell types: generally the type is the spell name.
'
+ +'
7.1(b) Spell Item-Classes
'
+ +'
'
+ +' MUSpellL# | A Wizard spell with the Level specified as a number |
'
+ +' PRSpellL# | A Priest spell with the Level specified as a number |
'
+ +' Power | A Power |
'
+ +'
'
+ +'
7.1(c) Spell Handedness
'
+ +'
0H A spell/power that does not take a hand (there is no Somatic component)
'
+ +'1H A spell/power that requires only 1 hand to cast (most spells are like this)
'
+ +'2H A spell/power that requires 2 hands to cast (perhaps a scroll must be held)
'
+ +'3H A spell/power that takes 3 hands... perhaps more than 1 caster together?
'
+ +'4H Etc No currently programmed spells use more than 2 hands
'
+ +'... ...
'
+ +'
7.1(d) Spell/Power Schools
'
+ +'
From MagicMaster v2.048 onwards, Spell Schools are specified by Class in the Class-DB definitions and, depending on the API configuration set with the --config command, will be checked by the system or otherwise. Those implemented so far for the Spells databases are:
'
+ +'
Abjuration, Alteration, Conjuration-Summoning, Enchantment-Charm, Divination, Illusion-Phantasm, Invocation-Evocation, Necromancy.
'
+ +'
Note that the \'/\' in School names have been replaced by hyphens. It is also allowed to use just one half of any hyphenated school name where appropriate. If a spell or power is of more than one school, separate each with a vertical bar character \'|\'
'
+ +'
'
+ +'
7.1(e) Magic Item Types
'
+ +'
There is an infinite list of magic item types: generally the type is the magic item name. A magic item can have more than one type, with each separated by a vertical bar character \'|\'
'
+ +'
7.1(f) Magic Item Classes
'
+ +'
Any magic item can have more than one class, each separated by a vertical bar \'|\'. It will then behave and be listed as each of the specified classes.
'
+ +'
'
+ +' Weapon | Weapons that are not Melee or Ranged weapons or any other class |
'
+ +' Magic | Magic attacks that are not melee or ranged attacks, often a spell or power of a magic item |
'
+ +' Melee | Melee weapons that are used in hand-to-hand combat |
'
+ +' Innate-Melee | Melee weapons that do not attract any proficiency penalties |
'
+ +' Ranged | Ranged weapons that are either thrown or fire ammunition |
'
+ +' Innate-Ranged | Ranged weapons that do not attract any proficiency penalties |
'
+ +' Ammo | All types of ammunition that is used by Ranged weapons |
'
+ +' Armour | Any type of armour that does not need to be held to work |
'
+ +' Armor | The same as Armour |
'
+ +' Helm | Any type of armour or clothing worn on the head |
'
+ +' Shield | A barrier that is held in hand(s) and defends against one or more attacks from the front |
'
+ +' Protection-cloak | Any type of clothing that has protective qualities |
'
+ +' Potion | Any type of potion, oil, pill or similar that is consumed or rubbed on |
'
+ +' Scroll | Scrolls and spell books, that contain one or multiple spells |
'
+ +' Scrollcase | An object that can hold a scroll |
'
+ +' Wand | Wands that cast spells or spell-like effects when wielded in the hand |
'
+ +' Staff | Quarterstaffs and similar large bludgeoning items that can also have spell-like abilities |
'
+ +' Rod | Walking-stick sized rods that can do spell-like effects, especially when used to attack |
'
+ +' Ring | Rings that are worn on a finger, one to each hand, that protect, have powers or spells |
'
+ +' Protection-Ring | Any special type of ring that imparts protective qualities |
'
+ +' Light | All types of lantern, torch, and other illumination |
'
+ +' DM-item | An item that only appears in a list button on the menu displayed by --gm-edit-mi |
'
+ +' Attack-macro | An attack macro template for a magic item held in a MI database |
'
+ +' Miscellaneous | Anything that does not fit in one of the other categories |
'
+ +' Unspecified | Items without any Specs section or an empty Class definition are listed under DM-Only |
'
+ +'
'
+ +'
7.1(g) Armour Handedness
'
+ +'
0H Items that do not require to be held to work (e.g. a Ring, Buckler or a Helm)
'
+ +'1H An item that must be held in one hand to work, such as a Wand
'
+ +'2H Items that need two hands to wield, like a Staff
'
+ +'3H Items that need three hands to use, perhaps by two characters...
'
+ +'... etc.
'
+ +'
7.1(h) Item Schools
'
+ +'
Currently, all Magic Items other than Weapons and Armour use the same set of magical schools as for Spells & Powers, as they mostly perform spell-like effects. See section 7.1(d) for the list.
'
+ +'
7.2 Data Sections
'
+ +'
Definitions for Data Section field types for Weapons & Armour can be found in the AttackMaster API documentation. Below are the definitions for Spell, Power & other Magical Item types.
'
+ +'
Note: 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.
'
+ +'
'
+ +' '
+ +' '
+ +' Field | '
+ +' Format | '
+ +' Default Value | '
+ +' Description | '
+ +' Can be used in | '
+ +'
'
+ +' '
+ +' Spell Data | '
+ +' Potion Data | '
+ +' Scroll Data | '
+ +' Wand Data | '
+ +' Staff Data | '
+ +' Rod Data | '
+ +' Ring Data | '
+ +' Misc Data | '
+ +' ToHit Data | '
+ +'
'
+ +' '
+ +' w: | < text > | \'-\' | Name to be displayed | | X | X | X | X | X | X | X | X |
'
+ +' w: | < text > | \'\' | Name of spell or power (Not case sensitive) | X | | | | | | | | |
'
+ +' +: | [ + / - ] # | 0 | Magical adjustment | | | | X | X | X | X | | X |
'
+ +' n: | # [ / # ] | 1 | Attacks per round | | | | X | X | X | | X | X |
'
+ +' st: | \' \' | \'\' | Item type to display | | X | X | X | X | X | X | X | |
'
+ +' sz: | [ t / s / m / l / h ] | \'\' | Size of item | | | | X | X | X | X | X | X |
'
+ +' sp: | [-]# or Dice Roll spec | 0 | Speed in segments (1/10 round) | X | X | X | X | X | X | X | X | X |
'
+ +' wt: | # | 1 | Weight of item in lbs | | X | | X | X | X | | X |
'
+ +' on: | command | \'\' | Cmd to execute when worn | | | | | | | X | |
'
+ +' off: | command | \'\' | Cmd to execute when removed | | | | | | | X | |
'
+ +' ns: | # | 0 | Number of stored spells & powers defined for item | | | X | X | X | X | X | X |
'
+ +' w: | < text > | \'-\' | Name of stored spell or power (Not case sensitive) | X | | X | X | X | X | X | X |
'
+ +' cl: | MU / PR / PW | \'\' | Type of stored spell or power | | | X | X | X | X | X | X |
'
+ +' lv: | # | 1 | Level at which spell/power is cast | | | | X | X | X | X | X | X |
'
+ +' pd: | -1 / # | 1 | Number per day (power only) | | | | X | X | X | X | X |
'
+ +' rc: | Charged / Uncharged / Rechargeable / Recharging / Self-chargeable / Cursed / Charged-Cursed / Recharging-Cursed / Self-chargeable-Cursed | Uncharged | Initial charged and Cursed status of item when found (Can be changed by DM using -gm-only-mi command once added to Character Sheet) Not case sensitive | | X | X | X | X | X | X | X | X |
'
+ +' c: | # | 1 | The number of charges expended by using a charged magic item. Uncharged items always use 0 charges | | X | X | X | X | X | X | X | X |
'
+ +' desc: | [MU-/PR-/PW-/MI-]name | \' \' | Power or Spell to display | | | X | | | | | | X |
'
+ +' msg: | < text > | \' \' | Attack message | | | X | | | | | | X |
'
+ +' cmd: | Command | \' \' | Attack API command | | | X | | | | | | X |
'
+ +'
'
+ +'
'
+ +'
7.3 Character Sheet data fields
'
+ +'
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 game-version-specific RPGMaster Library API for the game-version you are using. You can find the complete mapping for all APIs in the RPGMaster series, with an explanation of each, in a separate document - ask the Author for a copy.
'
+ +'
',
+ },
+ ClassDatabase_Help: {name:'Class & Race Database Help',
+ version:2.01,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Class & Race Database Help v2.01'
+ +'
'
+ +''
+ +'
Character Class & Race Databases
'
+ +'
for RPGMaster APIs
'
+ +'
1. General Database information
'
+ +'
The RPGMaster APIs use a number of databases to hold Macros defining races, creatures, character classes, spells, powers and magic items and their effects. Previous versions of the RPGMaster series of APIs held their databases all externally as character sheets: from this version onwards this is not the case for databases supplied with the APIs, which are now held internally to the APIs. However, the AttackMaster or MagicMaster API command --extract-db 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 definitions, and DMs can add their own 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:
'
+ +'
'
+ +' Wizard Spells: | additional databases: MU-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Priest Spells: | additional databases: PR-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Powers: | additional databases: Powers-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Magic Items: | additional databases: MI-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Character Classes: | additional databases: Class-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Races & Creatures: | additional databases: Race-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Attack Calculations: | additional databases: Attacks-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +'
'
+ +'
However: 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.
'
+ +'
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.
'
+ +'
Important Note: all Character Sheet databases must have their \'ControlledBy\' value (found under the [Edit] button at the top right of each sheet) set to \'All Players\'. 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.
'
+ +'
Each added database has a similar structure, with:
'
+ +'
'
+ +' - Ability Macros named as the class, spell, power or magic item specified, and used to describe and provide effects for classes, spells, powers and magic items using the commands in the RPGMaster APIs;
'
+ +' - 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 or Attack definitions);
'
+ +' - 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 Class entry below).
'
+ +'
'
+ +'
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 and magic item ability macros. When a Player or an NPC or Monster views or casts a spell, power or uses a magic item the Magic Master API runs 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.
'
+ +'
1.1 Replacing Races, Classes, Spells & Items
'
+ +'
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.
'
+ +'
'
+ +'
2. Character Class Database
'
+ +'
The DM can add Character Class databases as character sheets that have names that start with Class-DB. The Class definitions that come with the installed game-version-specific RPGMaster Library can be extracted to a character sheet and viewed by using the !magic --extract-db Class-DB or !attk --extract-db Class-DB commands. Note: it is best to delete the extracted Class-DB database character sheet after viewing/using, so that the system uses the much faster internal database version. After deleting or changing any character sheet database, always run the !magic --check-db or !attk --check-db command to re-index the databases.
'
+ +'
Classes: Class-DB-[added name]
'
+ +'
Those with version numbers of the form v#.# as part of the name will be ignored.
'
+ +'
As previously stated, each class definition has 3 parts in the database (see Section 1): an Ability Macro with a name that is unique and matches the Class being defined, an 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 others of the same base class: the base classes being "Warrior", "Wizard", "Priest", "Rogue", and "Psion". The quickest way to understand these entries is to examine existing entries. Do extract the root database using the --extract-db command and take a look (remember to delete it after viewing - see above)
'
+ +'
Note: The DM creating new classes does not need to worry about anything other than the Ability Macro in the database, as running the command --check-db will update all other aspects of the database appropriately for all databases, as long as the Specs and Data fields in the Ability Macros are correctly defined. Use the name of the particular database as a parameter to check and update just that database. Running the command --check-db with no parameters will check and update all databases.
'
+ +'
Ability macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
Standard / Simple Class definitions
'
+ +'
The Ability Macro for a Class may look something like this:
'
+ +'
Thief
'
+ +'
&{template:RPGMclass}{{name=Thief}}{{subtitle=Rogue Class}}{{Min Abilities=Dex:[[9]]}}{{Race=Any}}{{Hit Dice=1d6}}{{Alignment=Any not Lawful}}Specs=[Thief,RogueClass,0H,Rogue]{{=**Powers**}}{{1st Level=Thieving Abilities *Pick Pockets, Open Locks, Find/Remove Traps, Move Silently, Hide in Shadows, Detect Noise, Climb Walls,* and *Read Languages* Also, Thieves can *Backstab*}}{{10th Level=Limited ability to use magical & priest scrolls, with 25% chance of backfire}}ClassData=[w:Thief, hd:1d6, align:ng|nn|n|ne|cg|cn|ce, npp:-3, weaps:club|shortblade|dart|handxbow|lasso|shortbow|sling|broadsword|longsword|staff, ac:padded|leather|studdedleather|elvenchain|magicitem|ring|cloak]{{desc=Thieves come in all sizes and shapes, ready to live off the fat of the land by the easiest means possible. In some ways they are the epitome of roguishness.
'
+ +'The profession of thief is not honorable, yet it is not entirely dishonorable, either. Many famous folk heroes have been more than a little larcenous -- Reynard the Fox, Robin Goodfellow, and Ali Baba are but a few. At his best, the thief is a romantic hero fired by noble purpose but a little wanting in strength of character. Such a person may truly strive for good but continually run afoul of temptation.}}
'
+ +'
The ability specification for this Rogue class uses a Roll20 Roll Template, in this case defined by the RPGMaster Library (see the documentation for the Library for specifications of this Roll Template), but any Roll Template you desire can be used. The entries in the Roll Template itself can be anything you desire, giving as much or as little information as you want. However, the important elements for the RPGMaster APIs are those highlighted. Each of the elements important to the database are inserted between the elements of the Roll Template, meaning they will not be seen by the player when the macro is run. Generally spaces, hyphens and underscores in the data elements are ignored, and case is not significant. Each element is described below:
'
+ +'
Specs = [Character Class, Macro Type, Handedness, Base Class]
'
+ +'
The Specs section describes what Character Class and Base Class this is (and tells the APIs that this is a macro of type "Class"). These fields must be in this order. This format is identical for all database items, whether in these databases or others used by the RPGMaster series of APIs. Where there are multiple answers for a field, separate each by \'|\'. Note:Only A-Z, a-z, 0-9, hyphen/minus(-), plus(+), equals(=) point(.) and vertical bar(|) are allowed. Replace any forward slash with hyphen.
'
+ +'
'
+ +' Character Class | the Character Class name, often the same as the ability macro name. |
'
+ +' Macro Type | the type of the data in this Ability Macro, one of WarriorClass, WizardClass, PriestClass, RogueClass, or PsionClass. |
'
+ +' Handedness | #H, where # is the number of hands needed to be a character of this class (not currently used). |
'
+ +' Base Class | the base class that this class belongs to, one of Warrior, Wizard, Priest, Rogue, or Psion. |
'
+ +'
'
+ +'
ClassData=[w:Thief, hd:1d6, align:ng|nn|n|ne|cg|cn|ce, npp:-3, weaps:club|shortblade|dart|handxbow|lasso|shortbow|sling|broadsword|longsword|staff, ac:padded|leather|studdedleather|elvenchain|magicitem|ring|cloak]
'
+ +'
The ClassData section specifies the data relating to the class. These fields can be in any order.
'
+ +'
'
+ +' w: | <text> | the name of the class |
'
+ +' align: | <lg|ln|le|ng|nn|n|ne|cg|cn|ce> or <any> | the valid alignments for characters of this class, separated by \'|\' (not currently restricted) |
'
+ +' attr: | #[:#] | minimum and maximum starting attribute values (default is 3:18) |
'
+ +' race: | <list of races> or <any> | the races that can take this class, separated by \'|\' (not currently restricted) |
'
+ +' hd: | <dice roll spec> | the dice roll specification for hit points at each level (not currently used, for future expansion) |
'
+ +' npp: | <[-/+]#> | optional field to set a bespoke non-proficient weapon penalty for the character class. If not provided defaults to that for the Base Class. |
'
+ +' weaps: | <list of weapons & weapon types> or <any> | a vertical bar \'|\' separated list of weapons and weapon types that are valid for the class (see the Weapons database/documentation for types). Preceeding by \'!\' means \'not this weapon\' and with \'+\' means \'include this whatever\' |
'
+ +' ac: | <list of armour types> or <any> | a vertical bar \'|\' separated list of armour and armour types that are valid for the class (see the Weapons database/documentation for types). \'!\' and \'+\' work the same as for weapons |
'
+ +'
'
+ +'
The list of weapons and weapon types listed after the "weaps:" tag are checked by the system when a character tries to take a weapon in-hand using the "Change Weapons" dialogue or AttackMaster --weapon command, as determined by the API configuration setting, accessed via the MagicMaster or AttackMaster --config command. This configuration can be to restrict weapons to those listed ("Strict" mode), to give unlisted weapons a penalty of double the non-proficient weapon penalty for the base class ("Lax" mode), or to ignore this list and allow any weapon to be proficient or to just get the standard non-proficient weapon penalty ("Allowed" mode).
'
+ +'
In exactly the same way as for weapons, armour and armour types listed after the "ac:" tag are checked when calculating the Armour Class of the character using the "Check AC" dialogue or AttackMaster --checkac command, or automatically by the APIs at various points when AC might change, again according to the API configuration settings accessed via the --config command. This configuration can restrict a class to the armours and armour types listed for the class ("Rules" mode), or not restrict usage at all ("Allowed" mode).
'
+ +'
Three additional field tags are optionally available to allow the default weapon attacks per round progression to be overridden with a bespoke progression. Any one, two or all three can be specified: if just the progression level sequence is given, these levels will override the default levels, and similarly for the melee and ranged weapon mods, and defaults will be used or those not overridden. This only works for classes that are types of Warrior. The defaults are those specified for the Warrior class in the Player\'s Handbook.
'
+ +'
'
+ +' attkl: | <0|#|#|...> | a vertical bar \'|\' separated list of levels (the first must be 0) at which the next higher number of attacks per round is achieved. |
'
+ +' attkm: | <#|#|#|...> | a vertical bar \'|\' separated list of modifications to the standard number of attacks per round for any melee weapon used. Each can be an integer, a decimal float (# . #) or a fraction (# / #) |
'
+ +' attkr: | <#|#|#|...> | a vertical bar \'|\' separated list of modifications to the standard number of attacks per round for any ranged weapon used. Each can be an integer, a decimal float (# . #) or a fraction (# / #) |
'
+ +'
'
+ +'
Changing the Default Saving Throws
'
+ +'
The default Saving Throw table from the Player\'s Handbook can be overridden for any class definition. A new set of base saving throws by experience level can be defined.
'
+ +'
Dwarven Defender
'
+ +'
&{template:RPGMclass}{{name=Dwarven Defender}}{{subtitle=Warrior Class}}{{Min Abilities=Str:[[12]], Con:[[15]]}}{{Race=Dwarf only}}{{Alignment=Any}}Specs=[Dwarven Defender,WarriorHRClass,0H,Warrior]{{Hit Dice=1d12}}{{=**Powers**}}{{1st Level=*Defensive Stance* (1/4 levels per day}}ClassData=[w:Fighter, align:any, hd:1d12, race:dwarf, weaps:axe|club|flail|longblade|fencingblade|mediumblade|shortblade|polearm, ac:any, svl0:16|18|17|20|19, svl1:12|17|15|16|15, svl3:11|16|14|15|14, svl5:10|14|12|12|12, svl7:9|13|11|11|11, svl10:7|11|9|8|9, svl13:4|9|6|5|7, sv16:2|7|4|3|4, ns:1][cl:PW, w:Defensive-Stance, lv:1, pd:1l4]{{desc=The Dwarven defender is a formidable warrior. They are trained in the art of defence from a young age and make a defensive line nearly unbreakable.
'
+ +'The class is limited to Dwarves.
'
+ +'They can wear any armour but tend to go with the heaviest and toughest they can afford. They always use a shield, whenever possible a special Dwarven Tower shields (+1 in melee but +3 vs missiles when braced and in position). To use a Tower Shield requires a weapon proficiency slot. The dwarven Tower Shield has to be acquired in the campaign, it isn’t just granted to the character on creation (it’s a bit like a Paladins Warhorse). It may take many levels before they get a quest to acquire one.
'
+ +'They can only become proficient, specialise and double specialise in axes (not great axes) or hammers. They can never use missile weapons like a bow or crossbow but can throw hammers or axes.
'
+ +'They get bonus non weapon proficiency slots in Armourer, Blacksmithing and Mining.}}
'
+ +'
In addition to the elements described previously, the ClassData section specifies new elements regarding saving throws (ignore the ns: and everything beyond for now):
'
+ +'
ClassData=[w:Fighter, align:any, hd:1d12, race:dwarf, weaps:axe|club|flail|longblade|fencingblade|mediumblade|shortblade|polearm, ac:any, svl0:16|18|17|20|19, svl1:12|17|15|16|15, svl3:11|16|14|15|14, svl5:10|14|12|12|12, svl7:9|13|11|11|11, svl10:7|11|9|8|9, svl13:4|9|6|5|7, svl16:2|7|4|3|4, ns:1]
'
+ +'
Each svl# element specifies the base saves at and above experience level "#", for the five standard base save types, Paralysation, Poison & Death | Rod, Staff & Wand | Petrification & Polymorph | Breath Weapon | Spells. The highest specification element applies to all higher experience levels.
'
+ +'
Magic Items, Race definitions, and other database elements that affect a character can specify modifications to the base Saving Throws (whether using the defaults or custom Class specifications) by using the data element svXXX:[+-=]#,, where "XXX" is one of par, poi, dea, rod, sta, wan, pet, pol, bre, spe or all, followed by a colon, then a plus (+), a minus (-), an equals (=), and a number, or just a number with nothing before it. Each of the three-letter qualifiers refers to the relevant save, except "all" which applies the modifier to all saves. Preceeding the modifier amount by plus (+) or nothing improves the save by the modifier, preceeding by minus (-) worsens the save by the modifier, and by equals (=) overrides any other modifier being applied and applies only the modifier preceeded by the equals. Obviously, racial mods apply at all times (unless overridden by a magic item using the "=" modifier), and magic item mods only apply if the character has the magic item in their held items.
'
+ +'
Restricting the Schools and Spheres of Spells available
'
+ +'
While standard Wizards and Priests are very similar to the standard specification above, the definitions of specialist spellcaster classes is slightly more complex.
'
+ +'
Conjurer
'
+ +'
&{template:RPGMclass}{{name=Conjurer}}{{subtitle=Wizard Class}}{{Min Abilities=Int:[[9]], Con:[[15]]}}{{Alignment=Any}}{{Race=Human & Half Elf}}{{Hit Dice=1d4}}Specs=[Conjurer,WizardClass,0H,Wizard]{{=**Spells**}}{{Specialist=Conjuration / Summoning}}{{Banned=Greater Divination & Invocation}}ClassData=[w:Conjurer, hd:1d4, race:human|halfelf, sps:conjuration|summoning|conjurationsummoning, spb:greaterdivination|invocation, weaps:dagger|staff|dart|knife|sling, ac:magicitem|ring|cloak]{{desc=This school includes two different types of magic, though both involve bringing in matter from another place. Conjuration spells produce various forms of nonliving matter. Summoning spells entice or compel creatures to come to the caster, as well as allowing the caster to channel forces from other planes. Since the casting techniques and ability requirements are the same for both types of magic, conjuration and summoning are considered two parts of the same school.}}
'
+ +'
ClassData=[w:Conjurer, hd:1d4, race:human|halfelf, sps:conjuration|summoning|conjurationsummoning, spb:greaterdivination|invocation, weaps:dagger|staff|dart|knife|sling, ac:magicitem|ring|cloak]
'
+ +'
The ClassData for specialist casters includes additional tags to specify the schools/spheres of magic that the caster can and cannot use (and for priests major and minor access to spheres).
'
+ +'
'
+ +' sps: | <text|text|...> or <any> | a list of specialist schools or major spheres separated by vertical bars (\'|\') |
'
+ +' spb: | <text|text|...> | a list of banned schools/spheres that this class is not allowed to use separated by vertical bars (\'|\') |
'
+ +' spm: | <text|text|...> | a list of minor spheres (only relevant to Priest classes) separated by vertical bars (\'|\') |
'
+ +'
'
+ +'
The spellcaster will be restricted to memorising only spells from the schools/spheres listed depending on the API configuration using the --config command. The configuration can be to restrict to the specified schools/spheres ("Strict" mode) or allow all at any level ("Allowed" mode). The DM will also have a single button to add all valid spells at all levels to a Priest character sheet using the [Token-setup] macro or the !cmd --abilities command, and then using the [Add to Spellbook] / [Priest] dialogue.
'
+ +'
Default spells and spells per level
'
+ +'
Using the classes called "Wizard" or "Priest" will always grant the standard Wizard and Priest spells per level respectively as per the Player\'s Handbook, thus the class specifications are no different from that above. Also, any class name placed in the Wizard class fields (e.g. the second class definition column of the Advanced 2e sheet) will get standard Wizard spell casting capabilities (unless otherwise specified as below), and those in the Priest class fields (e.g. the third class definition column of the Advanced 2e sheet) will get standard Priest spell casting capabilities (unless otherwise specified as below).
'
+ +'
Non-standard spells per level
'
+ +'
A non-standard spellcaster (such as a Ranger, Paladin or Bard, or any class you wish to specify of a similar nature) can have their spellcasting capabilities specified in the class definition:
'
+ +'
Priest of Magic
'
+ +'
&{template:RPGMclass}{{name=Priest of Magic}}{{subtitle=Priest Class}}{{Min Abilities=Wis:[[12]], Int:[[13]]}}{{Race=Human or Half Elf}}{{Hit Dice=1d8}}{{Reference=*House Rules v16*}}{{=**Alignment**}}{{Deity=True Neutral}}{{Priests=Any Neutral}}{{Flock=Any Alignment}}{{ =**Spells**}}{{Major Spheres=All, Divination, Protection, Healing, Elemental}}{{Minor Spheres=Sun}}Specs=[Priest of Magic,PriestClass,0H,Priest]{{Powers=None}}ClassData=[w:Priest of Magic, hd:1d8, race:human|halfelf, align:ng|nn|n|ne, weaps:dagger|staff|dart|knife|sling, ac:any, sps:any, slv:4|3|12|MU, spl1:1|2|2|3|3|3|4|4|4|4|5|5, spl2:0|0|1|1|2|2|3|3|3|4|4|4, spl3:0|0|0|0|1|1|2|2|3|3|3|3, spl4:0|0|0|0|0|0|1|1|1|2|2|3],[w:Priest of Magic, sps:all|divination|protection|healing|elemental, spm:sun, slv:7|1|100|PR, spl1:1|2|2|3|3|3|3|3|3|3|3|3|3|3|4|4|4|4|4, spl2:0|0|1|1|2|2|3|3|3|3|3|3|3|3|3|4|4|4|4, spl3:0|0|0|0|0|1|1|2|2|3|3|3|3|3|3|3|4|4|4, spl4:0|0|0|0|0|0|0|0|1|1|2|2|3|3|3|3|3|4|4, spl5:0|0|0|0|0|0|0|0|0|0|0|1|1|2|2|3|3|3|4, spl6:0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|2|2|3, spl7:0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|1|2|2|2]{{desc=The Priest of Magic is an optional character class that can be used if your DM allows. It is a curious class in that it is a priest of the god of Magic, who then grants the priest the use of some limited Wizard spells as well as a slightly more restricted range of clerical spells.}}
'
+ +'
The Priest of Magic (a "House Rules" class for my group) can cast some Wizard spells at the expense of loosing some Priest spellcasting capability. Its class definition has ClassData for both "MU" and "PR" spells, in two separate sections (enclosed in each comma-separated \'[...]\').
'
+ +'
'
+ +' slv: | <#|#|#|(MU/PR)> | three numbers followed by either MU or PR (no brackets), separated by vertical bars (\'|\'). The first number is the highest level of spell that can be cast, the second the first class level at which spells can be cast, and the third the maximum casting level, followed by the class of spells being specified (MU=Wizard, PR=Priest) |
'
+ +' spl#: | <#|#|#|...> | for spells of level spl#, starting at the class level at which spells can be cast, the numbers of spells that can be cast at that and subsequent levels |
'
+ +'
'
+ +'
Classes with Specific Powers
'
+ +'
A character class can also be granted powers, and these can be specified in the class definition both as text for the Player to read, and also coded so the APIs can read them.
'
+ +'
Priest of Light
'
+ +'
&{template:RPGMclass}{{name=Priest of Light}}{{subtitle=Priest Class}}{{ =**Alignment**}}{{Deity=Neutral Good}}{{Priests=Any Good}}{{Flock=Any Neutral or Good}}{{Hit Dice=1d8}}Specs=[Priest of Light,PriesthoodClass,0H,Priest]{{ =**Powers**}}{{1st Level=*Infravision, Turn Undead*}}{{3rd Level=*Laying on Hands*}}{{5th Level=*Charm/Fascination*}}{{9th Level=*Prophecy*}}{{ =**Spells**}}{{Major Spheres=All, Charm, Divination, Healing and Sun}}{{Minor Spheres=Animal, Creation, Necromantic and Plant}}ClassData=[w:Priest of Light, align:LG|NG|CG, hd:1d8, weaps:bow|crossbow|dagger|dirk|dart|javelin|knife|slings|spear, ac:leather|padded|hide|magicitem|ring|cloak, sps:all|charm|divination|healing|sun, spm:animal|creation|necromantic|plant, ns:5][cl:PW, w:Infravision, lv:1, pd:-1][cl:PW, w:Turn Undead, lv:1, pd:-1][cl:PW, w:Laying on Hands, lv:3, pd:1][cl:PW, w:Charm-Fascination, lv:5, pd:1][cl:PW, w:Prophecy, lv:9, pd:1]{{desc=The god of all forms of light: Sunlight, moonlight, firelight, etc. The god is a friend of life, a patron of magic, a proponent of logical thought, and an enemy of the undead.
'
+ +'The priesthood of the god is devoted to celebrating these aspects of the god and to promoting positive forces such as healing.
'
+ +'Lesser gods of this attribute would be gods of one aspect of light. One god might be the god of Reason, another the god of Inspiration, etc.
'
+ +'This deity is as likely to be male as female.
'
+ +'The priests of this god are on good terms with the priests of Arts, Crafts, Darkness/Night, Dawn, Elemental Forces, Fire, Healing, Hunting, Literature/Poetry, Magic, Metalwork, Moon, Music/Dance, Oracles/Prophecy, and Sun.}}{{Reference=*The Complete Priest\'s Handbook* Sample Priesthoods}}
'
+ +'
The ClassData specification now has a tag of ns: which specifies a following number of sections enclosed in square brackets (\'[...]\'), each of which defines a single power granted to characters of this class. These sections include the following fields:
'
+ +'
'
+ +' cl: | <PW> | specifies the type of granted capability - for Class definitions, this is always PW (standing for Power) |
'
+ +' w: | <text> | the name of the power granted (which should match a definition in the Powers database Powers-DB) |
'
+ +' lv: | <#> | the character level at which they will gain this power |
'
+ +' pd: | < -1 / # / #L# > | the number of times per day the power can be used. A number, or -1 (meaning "at will"), or #L# which is first number per second number levels per day (e.g. 1L4 means once per day for L1 to L4, twice L5 to L8, etc) |
'
+ +'
'
+ +'
This allows the DM to use a single button to add all the specified powers to the Powers list of a specific character sheet using the [Token-Setup] macro or the !cmd --abilities command, and then using the [Add to Spellbook] / [Powers] dialogue. The Player will then only be able to memorise the appropriate powers for the character\'s level.
'
+ +'
3. Race & Creature Databases
'
+ +'
Exactly as with Character Classes, the DM can also add Race databases as character sheets that have names that start with Race-DB. The Race definitions that come with the installed game-version-specific RPGMaster Library can be extracted to a character sheet and viewed by using the !magic --extract-db Race-DB or !attk --extract-db Race-DB commands, and Creature definitions can be extracted by replacing "Race-DB" with "Race-DB-Creatures". Note: it is best to delete the extracted database character sheet after viewing/using, so that the system uses the much faster internal database version. After deleting or changing any character sheet database, always run the !magic --check-db or !attk --check-db command to re-index the databases.
'
+ +'
Races: Race-DB-[added name]
Creatures: Race-DB-Creatures-[added name]
'
+ +'
Those with version numbers of the form v#.# as part of the name will be ignored.
'
+ +'
As previously stated, each database definition has 3 parts in the database (see Section 1), the same as for the Class Database explanation above. Note: The DM creating new classes does not need to worry about anything other than the Ability Macro in the database, as running the command --check-db will update all other aspects of the database appropriately.
'
+ +'
Ability macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
3.1 Standard / Simple Race Definitions
'
+ +'
The database definition for a simple, standard Race might look something like this:
'
+ +'
Human
'
+ +'
&{template:RPGMdefault}{{name=Human}}{{subtitle=Race}}Specs=[Human,HumanoidRace,0H,Humanoid]{{Alignment=Any}}{{Languages=Often *common*}}{{Height=Males [60+2d10](!
/r 60+2d10 ins height)ins, Females [58+2d10](!
/r 58+2d10 ins height)ins}}{{Weight=Males [140+6d10](!
/r 140+6d10 lbs weight)lbs, Females [100+6d10](!
/r 100+6d10 lbs weight)lbs}}{{Life Expectancy=95 years}}{{Section=**Attributes**}}{{Minimum=None}}{{Maximum=None}}{{Adjustment=None}}{{Section1=**Powers**}}{{Section2=None}}{{Section3=**Special Advantages**}}{{Section4=None}}{{Section5=**Special Disadvantages**}}{{Section6=None}}RaceData=[w:Human, align:any, weaps:any, ac:any]{{desc=Although humans are treated as a single race in the AD&D game, they come in all the varieties we know on Earth. A human PC can have whatever racial characteristics the DM allows.
'
+ +'Humans have only one special ability: They can be of any character class and rise to any level in any class. Other PC races have limited choices in these areas.
'
+ +'Humans are also more social and tolerant than most other races, accepting the company of elves, dwarves, and the like with noticeably less complaint.
'
+ +'Because of these abilities and tendencies, humans have become significant powers within the world and often rule empires that other races (because of their racial tendencies) would find difficult to manage.}}
'
+ +'
As with Class definitions, and any other RPGMaster database entry, a Roll Template is used for formatting and the text in the template can be whatever you desire to display. The important elements for the RPGMaster APIs are highlighted and, as elsewhere, they are between the elements of the Roll Template to hide them when displayed, case is ignored and spaces, hyphens and underscores can be used but are ignored. Each element is described below:
'
+ +'
Specs=[Human,HumanoidRace,0H,Humanoid]
'
+ +'
The Specs section for a race describes the Sub-Race and base Race for the entry, and that this is a race definition. The fields must be in this order, identical for all database items.
'
+ +'
'
+ +' Sub-Race | the Sub-Race or Race name, often the same as the ability macro name. |
'
+ +' Macro Type | the type of the data in this Ability Macro, one of HumanoidRace, HumanoidCreature, or CreatureRace. |
'
+ +' Handedness | #H, where # is the number of hands needed to be a character of this race (not currently used). |
'
+ +' Base Race | the base race that this sub-race belongs to, and can be any other race in the database. For PCs generally one of Dwarf, Elf, Half-Elf, Halfling, Half-Orc, Human, or Gnome. |
'
+ +'
'
+ +'
The Sub-Race will "inherit" any data definitions and powers defined for the Base Race unless they are specifically overwritten or excluded by the Sub-Race definition. This reduces inconsistencies and the work of entering multiple duplications.
'
+ +'
RaceData=[w:Human, align:any, weaps:any, ac:any]
'
+ +'
All the same data fields (that are relevant) are available as for a Class definition. Where both the Class and Race of a character have specified restrictions or allowances, both the Class and the Race must allow an item / spell to be used. Whereas two Classes combine permissions as Class A OR Class B, Class and Race are Class AND Race. So a Warrior class can use a Greatsword, but a Warrior Gnome may not be able to use it as it would hit the ground as they wielded it!
'
+ +'
Save and To-Hit Modifiers
'
+ +'
There are a number of additional data fields relevant to Races:
'
+ +'
Halfling
'
+ +'
&{template:RPGMdefault}{{name=Halfling}}{{subtitle=Race}}{{Alignment=Any (Usually NG)}}Specs=[Halfling,HumanoidRace,0H,Humanoid]{{Languages=Often *common, halfling, dwarf, elf, gnome, goblin,* and *orc*}}{{Height=Males [32+2d8](!
/r 32+2d8 ins height)ins, Females [30+2d8](!
/r 30+2d8 ins height)ins}}{{Weight=Males [52+5d4](!
/r 52+5d4 lbs weight)lbs, Females [48+5d4](!
/r 48+5d4 lbs weight)lbs}}{{Life Expectancy=100 to 150 years}}{{Section=Attributes}}{{Minimum=Str:7, Con:7, Dex:10, Int:6}}{{Maximum=Wis:17}}{{Adjustment=Dex:+1, Str:-1}}{{Section1=Powers}}{{Expert Miners=Stouts can detect slopes, and approximate direction underground}}{{Section2=Special Advantages}}{{Infravision=Any halfling character has a 15% chance to have normal infravision (this means he is pure Stout), out to 60ft; failing that chance, there is a 25% chance that he has limited infravision (mixed Stout/Tallfellow or Stout/Hairfeets lineage), effective out to 30 feet.}}{{Magic Resistance=Magic-resistant, giving a bonus to saving throws against magical wands, staves, rods, and spells of +1 for every 3.5 points of Constitution score.}}{{Poison Resistance=Save vs. poison at +1 for every 3.5 points of Constitution score.}}{{Attack bonus=+1 To Hit with slings and thrown weapons}}{{Surprise=Enemies get a –4 penalty to surprise if the halfling is: 1) moving alone, 2) is 90 feet away from the rest of their party, or 3) is with other elves or halflings and all are in nonmetal armor. If the halfling must open a door or screen to get to the enemy, the penalty is reduced to –2.}}RaceData=[w:Halfling, align:any, weaps:any, ac:any, attr:str=7|con=7|dex=10|int=6|wis=1:17, thmod:throwing=1|dart=1|hand-axe=1|magical-stone=1|slings=1, svatt:con, svpoi:3.5 svrod:3.5, svsta:3.5, svwan:3.5, svspe:3.5, ns:2],[cl:PW,w:Detect Slope,lv:0,sp:0,pd:-1],[cl:PW,w:Determine Direction Underground,lv:0,sp:0,pd:-1]{{desc=Halflings are short, generally plump people, very much like small humans. Their faces are round and broad and often quite florid. Their hair is typically curly and the tops of their feet are covered with coarse hair. They prefer not to wear shoes whenever possible. Halflings see wealth only as a means of gaining creature comforts, which they love. Though they are not overly brave or ambitious, they are generally honest and hard working when there is need.
'
+ +'Elves generally like them in a patronizing sort of way. Dwarves cheerfully tolerate them, thinking halflings somewhat soft and harmless. Gnomes, although they drink more and eat less, like halflings best, feeling them kindred spirits. Because halflings are more open and outgoing than any of these other three, they get along with other races far better.
'
+ +'There are three types of halflings: Hairfeets, Tallfellows, and Stouts. Hairfeets are the most common type, but for player characters, any of the three is acceptable.}}
'
+ +'
'
+ +' attr: | #[:#] | minimum and maximum starting attribute values (default is 3:18) |
'
+ +' svXXX[+]: | [+ - =] # | saving throw modifiers |
'
+ +' thmod: | weapon=[+-]# | weapon=[+-]# | ... | a list of weapon type (or super-type) to-hit modifiers separated by vertical bars (\'|\') |
'
+ +'
'
+ +'
The saving throw modifiers are cumulative with those relevant to a Class and/or to worn/held magic items. The XXX can be one of att, par, poi, dea, rod, sta, wan, pet, pol, bre, spe or all, optionally followed by a "+" (see next paragraph), followed by a colon, then a plus (+), a minus (-), an equals (=), and a number, or just a number with nothing before it. Each of the three-letter qualifiers refers to the relevant save, except "all" which applies the modifier to all saves, and "att" which specifies an attribute by whose value any save may vary. Preceding the modifier amount by plus (+) or nothing improves the save by the modifier, preceding by minus (-) worsens the save by the modifier, and by equals (=) overrides any other modifier being applied and applies only the modifier preceded by the equals.
'
+ +'
If the XXX is followed by a "+" (e.g. like svpoi+:3), the save modifier will be a straight addition to (or subtraction from) the saving throw. Otherwise, the value of the attribute defined by the "svatt:" (which can be str, con, dex, int, wis, or chr, defaulting to con) is divided by the modifier provided and rounded down: e.g. if svatt:con and svpoi:3.5, a Constitution of 12 will result in a poison save bonus of 3.
'
+ +'
To-Hit modifiers are supplied as a list separated by vertical bars. Each entry is a weapon type or weapon super-type, followed by "=", followed by a number preceded by an optional "+" or "-". A plus (+) improves the chance of hitting, and a minus (-) is a penalty. Any weapon of the specified type or super-type will get the modifier.
'
+ +'
Race Powers
'
+ +'
As with classes, races can have specific powers. If a Sub-Race has a Base Race defined, the powers for both will be used - if you don\'t want any powers from a Base Race, do not specify one.
'
+ +'
Dwarf
'
+ +'
&{template:RPGMdefault}{{name=Dwarf}}{{subtitle=Race}}Specs=[Dwarf,HumanoidRace,0H,Humanoid]{{Alignment=Any (Usually LG)}}{{Height=4 to 4.5 ft}}{{Weight=150lbs}}{{Life Expectancy=350 years}}{{Languages=Often *Dwarf, Common, Orc, Kobold, Goblin, Gnome*}}{{Section=**Attributes**}}{{Min Attributes=Str:8, Con:11}}{{Max Attributes=Dex:17, Chr:17}}{{Attribute Adj.=Con:+1, Chr:-1}}{{Section1=**Powers**}}{{Infravision=*Infravision* to 60ft}}{{Expert Miners=Detect slopes, new tunnel construction, shifting walls, and stonework traps, and determine approximate depth underground}}{{Section2=**Special Advantages**}}{{Small size=Ogres, trolls, ogre magi, giants, and titans suffer a -4 penalty to attack Dwarves.}}{{Magic Resistance=Dwarves are nonmagical, which gives a bonus to dwarves\' saving throws against magical wands, staves, rods, and spells, of +1 for every 3.5 points of Constitution score.}}{{Sense Curses=Can sense a cursed item, but only if the device fails to function}}{{Section3=**Special Disadvantages**}}{{Item Failure=Magical items not specifically suited to the character\'s class have a 20% chance to malfunction when used.}}RaceData=[w:Dwarf, align:any, weaps:any, ac:any, attr:str=8|con=11|dex=1:17|chr=1:17, +:1|orc|half-orc|goblin|hobgoblin, -:4|ogre|troll|ogre-magi|oni|giant|titan, svatt:con,svpoi:3.5,svrod:3.5,svsta:3.5,svwan:3.5,svspe:3.5, ns:5],[cl:PW,w:Detect Slope,lv:0,sp:0,pd:-1],[cl:PW,w:Detect New Construction,lv:0,sp:0,pd:-1],[cl:PW,w:Detect Shifting Walls,lv:0,sp:0,pd:-1],[cl:PW,w:Detect Stonework Traps,lv:0,sp:0,pd:-1],[cl:PW,w:Determine Depth Underground,lv:0,sp:0,pd:-1]{{desc=Dwarves are short, stocky fellows, easily identified by their size and shape. They have ruddy cheeks, dark eyes, and dark hair. Dwarves tend to be dour and taciturn. They are given to hard work and care little for most humor. They are strong and brave. They enjoy beer, ale, mead, and even stronger drink. Their chief love, however, is precious metal, particularly gold. They prize gems, of course, especially diamonds and opaque gems (except pearls, which they do not like). Dwarves like the earth and dislike the sea. Not overly fond of elves, they have a fierce hatred of orcs and goblins. Their short, stocky builds make them ill-suited for riding horses or other large mounts (although ponies present no difficulty), so they tend to be a trifle dubious and wary of these creatures. They are ill-disposed toward magic and have little talent for it, but revel in fighting, warcraft, and scientific arts such as engineering.
'
+ +'Though dwarves are suspicious and avaricious, their courage and tenacity more than compensate for these shortcomings.
'
+ +'Dwarves typically dwell in hilly or mountainous regions. They prefer life in the comforting gloom and solidness that is found underground.}}
'
+ +'
As master miners, Dwarves have a number of powers that they can call on when underground, to assess their situation. These use the same syntax for specification as for Classes with powers.
'
+ +'
Dwarves also have to-hit and AC bonuses when facing various types of creature. These are specified in the race data as follows:
'
+ +'
'
+ +' +: | [+-] # | race/creature | race/creature | ... | a modifier to hit of # when attacking any listed creature (not currently implemented) |
'
+ +' -: | [+-] # | race/creature | race/creature | ... | a modifier to AC of # when being attacked by any listed creature (not currently implemented) |
'
+ +'
'
+ +'
A positive modifier is always a benefit, and a negative one is a penalty. These are not currently implemented as the APIs cannot know what race the opponent is, unless a targeted attack is used (see attackMaster API help handout for information on attacks) and targeted attacks are a DM and Player option which is not mandatory.
'
+ +'
4. Creatures
'
+ +'
The same specification approach can be used to define creatures other than humanoids, and humanoids other than PCs and NPCs. A number of such definitions are provided in the Race-DB-Creatures database, which can be extracted to a Character Sheet DB using the !magic --extract-db Race-DB-Creatures command. All the same data fields are available as for Race definitions, with some extras.
'
+ +'
Vampire
'
+ +'
&{template:RPGMdefault}{{name=Vampire}}{{subtitle=Creature}}{{Alignment=Usually Chaotic Evil}}Specs=[Vampire,HumanoidCreature,0H,Creature]{{Languages=Whatever they knew before they were a vampire, or what their vampire parents taught them.}}{{Height=As per pre-vampire race (usually [65+2d6](!
/r 65+2d6 ins height)ins,}}{{Weight=Their weight before becoming a vampire or [140+6d10](!
/r 140+6d10 lbs weight)lbs}}{{Life(?) Expectancy=Immortal}}{{Section=**Attributes**}}{{Minimum=Str:18(76), Int:15}}{{Maximum=Int:16}}{{Adjustment=None}}{{Section1=**Powers**}}{{Energy Drain=Drains 2 levels from anyone they successfully touch}}{{Charm=Any person who allows the vampire to look into their eyes will be affected as if by a *charm person* spell. Due to the power of this enchantment, a -2 is applied to the victim\'s saving throw vs. spell}}{{Summon Creatures=Can summon swarms of creatures to their aid}}{{Spell-like powers=*Gaseous Form* and *Spider Climb* at will}}{{Section2=**Special Advantages**}}{{Infravision=60 feet}}{{Shape Change=Can *Shape Change* into a large bat at will}}{{Plus Weapons To Hit=Attackers must use weapons of at least +1 to be able to hit a vampire}}{{Immunities=Immune to *Sleep, Charm,* and *Hold* spells, Paralysis and Poison. Spells based on cold or electricity cause only half damage}}{{Section3=**Special Disadvantages**}}{{Repellants=Odor of Strong Garlic; Mirror or Holy Symbol presented with conviction}}{{Holy Water or Symbol=Burns a vampire for 2-7 (1d6+1) damage with a successful hit}}{{Others=See Monsterous Compendium for other disadvantages}}RaceData=[w:Vampire, cattr:int=15:16|ac=1|mov=12|fly=18C|hd=8d8+3|thac0=11|attk1=hand:4+1d6:0:B,spattk:Energy drain,spdef:+1 weapon to hit; immune to *sleep, charm & hold*, ns:5],[cl:PW,w:Charm Person,sp:1,lv:0,pd:-1],[cl:PW,w:Summon Swarm,sp:2,lv:0,pd:-1],[cl:PW,w:Gaseous Form,sp:0,lv:0,pd:-1],[cl:PW,w:MU-Shape-Change,sp:9,lv:0,pd:-1],[cl:PW,w:Spider Climb,sp:1,lv:0,pd:-1]{{desc=Of all the chaotic evil undead creatures that stalk the world, none is more dreadful than the vampire. Moving silently through the night, vampires prey upon the living without mercy or compassion. Unless deep underground, they must return to the coffins in which they pass the daylight hours, and even in the former case they must occasionally return to such to rest, for their power is renewed by contact with soil from their graves.
'
+ +'One aspect that makes the vampire far more fearful than many of its undead kindred is its appearance. Unlike other undead creatures, the vampire can easily pass among normal men without drawing attention to itself for, although its facial features are sharp and feral, they do not seem inhuman. In many cases, a vampire\'s true nature is revealed only when it attacks. There are ways in which a vampire may be detected by the careful observer, however. Vampires cast no reflection in a glass, cast no shadows, and move in complete silence.}}
'
+ +'
Creatures have additional data fields that set up all the important fields for the APIs on the AD&D2e Character Sheet (only when the creature is specified using the Class/Race menu on the "token-setup" menu - just typing the creature type into the Race field on the Character Sheet will not do this).
'
+ +'
'
+ +' spattk: | text | special attacks text to be displayed when the Specials Action Button is used |
'
+ +' spdef: | text | special defenses text to be displayed when the Specials Action Button is used |
'
+ +' cattr: | attr=value | attr=value | ... | a list of attribute/value pairs, where attr is one of: |
'
+ +' ac | #[:#] | creature armour class |
'
+ +' mov | # | creature movement on the ground |
'
+ +' fly | text | creature movement in the air |
'
+ +' sw | text | creature movement when swimming |
'
+ +' hd | #[d#][+/-#][r#] | creature hit dice roll spec |
'
+ +' hp | #[:#] | creature hit points |
'
+ +' regen | # | creature regeneration HP/round |
'
+ +' thac0 | # | creature Thac0 |
'
+ +' tohit | [+/-]# | creature to-hit modifier |
'
+ +' dmg | [+/-]# | creature damage modifier |
'
+ +' crith | # | creature critical hit roll |
'
+ +' critm | # | creature critical miss roll |
'
+ +' attk1 | text,roll,speed,type | specification for creature innate attack 1 |
'
+ +' attk2 | text,roll,speed,type | specification for creature innate attack 2 |
'
+ +' attk3 | text,roll,speed,type | specification for creature innate attack 3 |
'
+ +' attkmsg | text[$$text][$$text] | message(s) for attacks |
'
+ +' speed | # | creature overall attack speed |
'
+ +' cl | [F/MU/PR/RO/PS]:Class name | Give creature a NPC class |
'
+ +' lv | # | Give crature a NPC level |
'
+ +'
'
+ +'
When a creature (or race) with these data fields is selected in the Race/Class menu, the CommandMaster API automatically sets all of the respective Character Sheet attributes to the specified values. In fact, all of these data fields can be used with a standard race, but are less useful.
'
+ +'
4.1 Specifying Creature Weapons & Armour
'
+ +'
Many creatures have attacks using their claws, bites and other "innate" attacks, and have tough natural armoured skin. However, many humanoid creatures can use normal weapons & armour to attack adventurers and defiend themselves. It is possible to specify the possible weapon combinations and available armour for each creature type, and add a randomness to the selection criteria, as this example shows:
'
+
+ +'
The additional RaceData datasets highlighted have the following fields:
'
+ +'
'
+ +'cl | WP / AC | Type of data in the dataset. WP = weapon, AC = armour |
'
+ +'% | # | Chance of dataset being used relative to others of same type (does not have to add up to 100) |
'
+ +'prime | weapon : qty | Name & quantity of weapon to take in Primary hand. Only 1 is taken in-hand, rest of qty held in items |
'
+ +'offhand | weapon : qty | Name & quantity of weapon to take in Off-hand hand. Only 1 is taken in-hand, rest of qty held in items |
'
+ +'both | weapon : qty | Name & quantity of two-handed weapon to take in both hands. Only 1 is taken in-hand, rest of qty held in items |
'
+ +'items | weap/armour:qty | weap/armour:qty | ... | Name & quantity of weapons or armours to store as items of equipment. Armour will automatically contribute to creature armour class |
'
+ +'
'
+ +'
5. Specs & Data field values
'
+ +'
Below are lists of the current possible values for the Class and Race database Ability macro sections.
'
+ +'
5.1 Specs sections
'
+ +'
Specs=[Class Type, Macro Type, Handedness, Class Group-Type]
'
+ +'
Specs=[Sub-Race, Macro Type, Handedness, Base-Race]
'
+ +'
There are no default settings for any of the Specs data fields. All must be explicitly specified.
'
+ +'
5.1(a) Class & Race Types
'
+ +'
There is an infinite list of class types: generally the type is the class name.
'
+ +'
There is an infinite list of race and creature types: generally the type is the sub-race or creature name.
'
+ +'
5.1(b) Macro Type
'
+ +'
Classes: One of "WarriorClass", "WizardClass", "PriestClass", "RogueClass", "PsionClass", relating to the base class of the character. This field is used to add the Class name to the right base class list for selection by the Players.
'
+ +'
Races: One of "HumanoidRace", "HumanoidCreature", "CreatureRace", relating to the base race of the character. This field is used to add the Race name to the right race or creature list for selection.
'
+ +'
5.1(c) Handedness
'
+ +'
0H A Race, Creature or Class that can only be taken by characters and creatures that do not have hands (e.g. a fish-type creature)
'
+ +'1H A Race, Creature or Class that can only be taken by characters or creatures with only one hand (e.g. a snake NPC that can use its prehensile tail to hold weapons)
'
+ +'2H A Race, Creature or Class that has two hands - the normal for humanoid PCs and NPCs
'
+ +'3H A Race, Creature or Class that can only be taken by characters or creatures with three or more hands
'
+ +'4H Etc
'
+ +'... ...
'
+ +'
(Handedness for Race and Classes are not currently restricted or used by the system. In future, the number of hands specified on the "Change Weapon" dialogue may be related to the Character Race & Class)
'
+ +'
5.1(d) Base Classes
'
+ +'
The Base Class can currently be one of "Warrior", "Wizard", "Priest", "Rogue" or "Psion". If a character class is allowed to be of more than one base class, separate each with a vertical bar character \'|\'. This determines the valid Character Sheet fields that this Class Type can appear in.
'
+ +'
The Base Race or Creature Type can be for any other Race or Creature definition. Multiples are not allowed (no vertical bars \'|\'), and the Sub-Race / Creature will inherit the specifications and powers of the Base Race / Creature.
'
+ +'
'
+ +'
5.2 Data Sections
'
+ +'
Below are the definitions for each of the possible ClassData and RaceData fields.
'
+ +'
Note: 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.
'
+ +'
'
+ +' '
+ +' '
+ +' Field | '
+ +' Format | '
+ +' Default Value | '
+ +' Description | '
+ +'
'
+ +' '
+ +' w: | < text > | \'Fighter\' | Name of the Class |
'
+ +' hd: | Dice Roll spec | 0 | Hit dice roll per level |
'
+ +' align: | [ lg / ng / cg / ln / nn / n / cn / le / ne / ce / any ] | any | Allowed alignments |
'
+ +' race: | < text | text | ... > or any | any | Allowed races |
'
+ +' weaps: | < text | text | ... > or any | any | Allowed weapons and weapon types |
'
+ +' npp: | [-]# | \'\' | The weapon non-proficiency penalty for the class |
'
+ +' twp: | [-]#.# | 2.4 | The two weapon penalty (primary.secondary) for the class |
'
+ +' ac: | < text | text | ... > or any | any | Allowed armour types |
'
+ +' attkl: | < 0 | # | # | ... > | \'\' | Class level progression for "attacks per round" modifiers |
'
+ +' attkm: | < # | # | # | ... > | \'\' | Melee weapon "attacks per round" modifiers by class level progression |
'
+ +' attkr: | < # | # | # | ... > | \'\' | Ranged weapon "attacks per round" modifiers by class level progression |
'
+ +' sps: | < text | text | ... > or any | any | Allowed spell schools or major spheres |
'
+ +' spm: | < text | text | ... > | \'\' | Allowed minor spheres |
'
+ +' spb: | < text | text | ... > | \'\' | Banned spell schools |
'
+ +' slv: | < # | # | # | <MU / PR> > | \'\' | Non-standard spellcaster level/type specification |
'
+ +' spl# | < # | # | # | ... > | \'\' | No. of spells of level spl# at each character level |
'
+ +' attr: | #[:#] | 3:18 | minimum and maximum starting attribute values |
'
+ +' svXXX[+]: | [+ - =] # | 0 | saving throw modifiers |
'
+ +' thmod: | weapon=[+-]# | weapon=[+-]# | ... | \'\' | a list of weapon type (or super-type) to-hit modifiers separated by vertical bars (\'|\') |
'
+ +' +: | [+-] # | race/creature | race/creature | ... | \'\' | a modifier to hit of # when attacking any listed creature (not currently implemented) |
'
+ +' -: | [+-] # | race/creature | race/creature | ... | \'\' | a modifier to AC of # when being attacked by any listed creature (not currently implemented) |
'
+ +' spattk: | text | \'\' | special attacks text to be displayed when the Specials Action Button is used |
'
+ +' spdef: | text | \'\' | special defenses text to be displayed when the Specials Action Button is used |
'
+ +' cattr: | attr=value | attr=value | ... | \'\' | a list of attribute/value pairs, where attr defines a field on the Character Sheet Monster tab |
'
+ +' ns: | # | 0 | Number of granted spells/powers defined for item |
'
+ +' cl: | < MU / PR / PW > | \'\' | Type of granted spell/power (always PW=Power) |
'
+ +' w: | < text > | \'-\' | Name of granted spell/power |
'
+ +' lv: | # | 1 | The character level at which the Power is granted |
'
+ +' pd: | [ -1 / # / #L# ] | 1 | No. of times per day power can be used. -1 is "at will", and #L# is first number per second number levels, per day |
'
+ +'
'
+ +'
'
+ +'
5.3 Character Sheet data fields
'
+ +'
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 RPGMaster Library 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.
'
+ +'
',
+ },
+ AttacksDatabase_Help:{name:'Attacks Database Help',
+ version:1.04,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Attacks Database Help v1.04'
+ +'
'
+ +''
+ +'
Attacks Database
'
+ +'
for RPGMaster APIs
'
+ +'
1. General Database information
'
+ +'
The RPGMaster APIs use a number of databases to hold Macros defining character classes, spells, powers and magic items and their effects. Previous versions of the RPGMaster series of APIs held their databases all externally as character sheets: from this version onwards this is not the case for databases supplied with the APIs, which are now held internally to the APIs. However, the AttackMaster or MagicMaster API command --extract-db 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 definitions, and DMs can add their own 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:
'
+ +'
'
+ +' Wizard Spells: | additional databases: MU-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Priest Spells: | additional databases: PR-Spells-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Powers: | additional databases: Powers-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Magic Items: | additional databases: MI-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Character Classes: | additional databases: Class-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Character Races: | additional databases: Race-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Attack Calculations: | additional databases: Attacks-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +' Fighting Styles: | additional databases: Styles-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +'
'
+ +'
However: 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.
'
+ +'
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.
'
+ +'
Important Note: all Character Sheet databases must have their \'ControlledBy\' value (found under the [Edit] button at the top right of each sheet) set to \'All Players\'. 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.
'
+ +'
Each added database has a similar structure, with:
'
+ +'
'
+ +' - Ability Macros named as the class, spell, power or magic item specified, and used to describe and provide effects for classes, spells, powers and magic items using the commands in the RPGMaster APIs;
'
+ +' - 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 or Attack definitions);
'
+ +' - 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 Class entry below).
'
+ +'
'
+ +'
However, as with all other Databases in the RPGMaster Suite of APIs, if the Ability Macros are correctly set up using the formats detailed in the Help Documentation, the AttackMaster API command !attk --check-db database-name will check the database and set up all other aspects for you, including the correct Custom Attributes and List entries.
'
+ +'
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 and magic item ability macros, and are an essential part of Attack Templates. When a Player or an NPC or Monster makes an attack, the AttackMaster API runs 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.
'
+ +'
1.1 Replacing Database Items
'
+ +'
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 (a database with the same root name) with the Ability Macro you create having 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.
'
+ +'
'
+ +'
2. How Attacks Work
'
+ +'
In order to understand the Attacks Database, it is first important to understand how attacks are executed by the AttackMaster API. Under some (if not all) versions of D&D, and especially AD&D 2nd Edition, attacks are quite complex involving many factors that can vary from moment to moment. Some say that this is why they prefer RPG systems that require less maths and are faster to execute, that the complexity of the AD&D2e combat system interrupts the flow of play. The AttackMaster API handles attacks in such a way as to hide as much of that complexity from the players as possible, and thus allow game-play to flow and players to concentrate on the unfolding story.
'
+ +'
In order for the API to achieve this, it must evaluate many factors "on the fly" such as current magical effects in place (generally or on individuals), the current attributes of a character (which can vary as they are affected by game play), the type, range and properties of the weapon combinations used at that point in time for that particular attack, and the effects of the race, class, level and proficiency of the character, among several others. Given that these factors can vary even during a single round, each attack must be fully evaluated from scratch each time it is made.
'
+ +'
Another issue is introduced by players feeling much more satisfied if they can see dice rolling for the attack, or they may want to use the Roll20 dice rolling mouse action, or even their own physical dice. Unfortunately for API authors, at the time of writing the API it is only possible to display rolling 3D dice from Chat Window dice rolls, either typed in the entry box by the player or run from Macros displayed in the Chat Window - 3D dice will not work when called by or included in API calls and commands.
'
+ +'
So how does the AttackMaster API achieve 3D dice rolls and attack calculations that can accelerate game-play? The answer is that it uses Attack Template definitions which it parses and turns into Ability Macros on the Character Sheet of the character that selects to do an attack. The Melee Weapon templates are parsed and the attack Ability Macros for each Melee weapon in-hand created on the Character Sheet as (in fact just before) the Attack chat window menu is displayed, and Ranged Weapon templates are parsed and their attack Ability Macros are created after the type of Ammo has been selected and just before the relevant range buttons on the Attack menu are enabled for the Player to select. Monster attack templates are parsed just before the Monster Attack menu is shown, with a template "set" created for each defined Monster innate attack on the Monster character sheet tab. When the Player selects a Melee weapon to attack with, or the relevant range button for a Ranged weapon or Monster attack, the API is then not actually involved at all - the Roll20 Chat Window button just selected is just doing a standard macro call to the relevant attack Ability Macro just created on the Character Sheet. This also means the actual attacks happen at the fastest speed Roll20 can achieve as no API code is being run at that point.
'
+ +'
'
+ +'
3. The Attacks Database
'
+ +'
The Attack Templates are stored in the internal API Attacks Database, which can be exposed in Character Sheet Database form as Attacks-DB using the AttackMaster !attk --extract-DB Attacks-DB command. Attack Templates can also exist in additional bespoke Attacks Databases the DM/Game Creator adds using the Character Sheet name Attacks-DB-[added name]. There are 12 basic Attack Templates:
'
+ +'
'
+ +' MW-ToHit | Melee Weapon calculation to assess and display the Armour Class hit by an attack |
'
+ +' MW-DmgSM | Melee Weapon calculation to assess the damage done to a Medium or smaller opponent if the hit was sucessful |
'
+ +' MW-DmgL | Melee Weapon calculation to assess the damage done to Large or larger opponents as a result of a successful hit |
'
+ +' MW-Targeted-Attk | Melee Weapon calculation for using a targeted attack which rolls all attack and damage dice at once, and then displays the AC hit, the damage vs. all types of opponents, and the current AC & HP of the targeted opponent |
'
+ +' RW-ToHit | Ranged Weapon calculation to assess and display the Armour Class hit by an attack |
'
+ +' RW-DmgSM | Ranged Weapon calculation to assess the damage done to a Medium or smaller opponent if the hit was sucessful |
'
+ +' RW-DmgL | Ranged Weapon calculation to assess the damage done to Large or larger opponents as a result of a successful hit |
'
+ +' RW-Targeted-Attk | Ranged Weapon calculation for using a targeted attack which rolls all attack and damage dice at once, and then displays the AC hit, the damage vs. all types of opponents, and the current AC & HP of the targeted opponent |
'
+ +' Mon-Attk | Monster/Creature attack calculation to assess and display the Armour Class hit by an attack |
'
+ +' Mon-DmgSM | Monster/Creature damage calculation to assess and display the damage done to Medium or smaller opponets by an attack |
'
+ +' Mon-DmgL | Monster/Creature damage calculation to assess and display the damage done to a Large or larger opponent by an attack |
'
+ +' Mon-Targeted-Attk | Monster/Creature for a targeted attack calculation to assess and display the Armour Class hit and damage done by an attack, along with the target\'s current AC and HP |
'
+ +'
'
+ +'
The Melee Weapon Attack Templates will be parsed for each Melee Weapon in-hand at the time of the attack, and the Ranged Weapon Attack Templates will be parsed for each possible range of the Ranged Weapon/Ammo combination selected for the attack. Two additional Melee Weapon Attack Templates are parsed if the character making the attack is a Rogue class:
'
+ +'
'
+ +' MW-Backstab-DmgSM | Melee Weapon calculation to assess the damage done to a Medium or smaller opponent if the hit was a Rogue doing a backstab and the attack was successful |
'
+ +' MW-Backstab-DmgL | Melee Weapon calculation to assess the damage done to a Large or larger opponent if the hit was a Rogue doing a backstab and the attack was successful |
'
+ +'
'
+ +'
All of the above templates are provided in the Attacks-DB database supplied with the game version-specific RPGMaster Library API. They are created to follow the rules of the game version supported by that specific library: DMs and Game Creators can create their own attack and damage calculations following whatever rules they want in their own bespoke Attacks Database, using the information provided in the next section.
'
+ +'
It is possible to add additional Attack Templates that are specific to particular Races, Classes, or even individual weapons! Indeed, the database supplied includes an example of a bespoke Attack Template set for a thrown prepared Oil Flask. When an attack is the action selected by the Player, the API will search the Attacks-DB and bespoke user Attacks Databases for Melee and Ranged Attack Templates in the following name order (replace the ?W with either MW or RW as appropriate):
'
+ +'
'
+ +' - ?W-ToHit-\< weapon name \> Searches for a weapon-specific Attack Template set for the weapon being used to attack with, but if not found then
'
+ +' - ?W-ToHit-\< class name \> Searches for a class-specific Attack Template set for the class (or each class of a multi/dual class) of the attacking character, but if not found then
'
+ +' - ?W-ToHit-\< race \> Searches for a race-specific Attack Template set for the race of the attacking character, but if not found then
'
+ +' - ?W-ToHit Uses the default Attack Template set.
'
+ +'
'
+ +'
'
+ +'
4. Attack Data Fields
'
+ +'
Attack Templates can take the form of any message or macro that can be held in a Roll20 Character Sheet Ability Macro and be displayed in the Chat Window when called. Typically, this will use a Roll Template (standard Roll20 functionality - see Roll20 Help for information), but it can be any format you desire as long as it results in the correct display of information to the Player.
'
+ +'
The Attack Template has a large number of template fields that it can call upon to use in its calculations - these are pre-calculated values supplied by the API that the DM / Game Creator writing a new Attack Template can use. The standard Roll20 attribute value notation of @{selected|field-name} is not recommended for use in Attack Templates, as when the template is parsed, and then later the resulting Ability Macro run as part of the attack, there are circumstances where the token for the attacking Character may not be currently selected, resulting in the wrong value being used or, worse, an error occurring and the game halting. Instead, all the following template fields are available:
'
+ +'
'
+ +' '
+ +' All Attack Templates |
---|
'
+ +'
'
+ +' ^^toWho^^ | Resolves to a Roll20 whisper command to the Character making the attack |
'
+ +' ^^toWhoPublic^^ | Resolves to a Roll20 chat command to the GM if a GM controlled creature is making the attack, otherwise a public message to all Players |
'
+ +' ^^defaultTemplate^^ | Resolves to the name of the Default Roll Template name set in the AttackMaster API |
'
+ +' ^^cname^^ | Resolves to the Character Name of the attacking character |
'
+ +' ^^tname^^ | Resolves to the Token Name of the attacking character |
'
+ +' ^^cid^^ | Resolves to the Roll20 Character ID of the attacking character |
'
+ +' ^^tid^^ | Resolves to the Roll20 Token ID of the attacking character |
'
+ +' ^^toHitRoll^^ | Depending on if the Player chose for Roll20 to roll the attack dice or to roll their own dice, resolves to one of (a) the attack dice specification provided in the Attack Template\'s Specs field, or (b) a Roll Query requesting the Player to enter a dice roll result |
'
+ +' ^^thac0^^ | Resolves to the base thac0 (value "to hit armour class 0") of the attacking character without any adjustments |
'
+ +' ^^ACfield^^ | Resolves to the Character Sheet field name that holds the target creatures current Armour Class (only used in targeted attacks) |
'
+ +' ^^targetACfield^^ | Resolves to the targeted token value Armour Class macro call @{target|Select Target|^^ACfield^^} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^HPfield^^ | Resolves to the Character Sheet field name that holds the target creatures current Hit Points (only used in targeted attacks) |
'
+ +' ^^targetHPfield^^ | Resolves to the targeted token value Hit Points macro call @{target|Select Target|^^HPfield^^} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^magicAttkAdj^^ | Resolves to any magical effect attack bonus or penalty resulting from magic currently in effect |
'
+ +' ^^strAttkBonus^^ | Resolves to the strength to-hit bonus/penalty of the attacking character |
'
+ +' ^^strDmgBonus^^ | Resolves to the strength damage bonus/penalty of the attacking character |
'
+ +' ^^slashWeap^^ | Resolves to 1 if the damage type of the weapon includes Slashing (or S), otherwise 0 |
'
+ +' ^^pierceWeap^^ | Resolves to 1 if the damage type of the weapon includes Piercing (or P), otherwise 0 |
'
+ +' ^^bludgeonWeap^^ | Resolves to 1 if the damage type of the weapon includes Bludgeoning (or B), otherwise 0 |
'
+ +' ^^weapType^^ | Resolves to the 3 letter damage type of the weapon (S, P, B or any combination) |
'
+ +' ^^ACvsNoMods^^ | Resolves to the targeted standard Armour Class macro call @{target|Select Target|AC-field} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^ACvsSlash^^ | If a slashing weapon, resolves to the targeted Slashing damage Armour Class macro call @{target|Select Target|SlashAC-field} vs. a targeted opponent, otherwise is blank (only used in targeted attacks) |
'
+ +' ^^ACvsPierce^^ | If a piercing weapon, resolves to the targeted Piercing Armour Class macro call @{target|Select Target|PierceAC-field} vs. a targeted opponent, otherwise is blank (only used in targeted attacks) |
'
+ +' ^^ACvsBludgeon^^ | If a bludgeoning weapon, resolves to the targeted Bludgeoning Armour Class macro call @{target|Select Target|BludgeonAC-field} vs. a targeted opponent, otherwise is blank (only used in targeted attacks) |
'
+ +' ^^ACvsNoModsTxt^^ | Resolves to the text "No Mods" |
'
+ +' ^^ACvsSlashTxt^^ | If this is a slashing weapon, resolves to the text "Slash", otherwise resolves to an empty string |
'
+ +' ^^ACvsPierceTxt^^ | If this is a piercing weapon, resolves to the text "Pierce", otherwise resolves to an empty string |
'
+ +' ^^ACvsBludgeonTxt^^ | If this is a bludgeoning weapon, resolves to the text "Bludgeon", otherwise resolves to an empty string |
'
+ +' ^^ACvsSTxt^^ | If this is a slashing weapon, resolves to the text "S", otherwise resolves to an empty string |
'
+ +' ^^ACvsPTxt^^ | If this is a piercing weapon, resolves to the text "P", otherwise resolves to an empty string |
'
+ +' ^^ACvsBTxt^^ | If this is a slashing weapon, resolves to the text "B", otherwise resolves to an empty string |
'
+ +'
'
+ +'
'
+ +'
'
+ +' '
+ +' Monster Attack Templates |
---|
'
+ +'
'
+ +' ^^attk1^^ | Resolves to the name of the creature\'s attack 1, if provided (applies to monster attacks only) |
'
+ +' ^^attk2^^ | Resolves to the name of the creature\'s attack 2, if provided (applies to monster attacks only) |
'
+ +' ^^attk3^^ | Resolves to the name of the creature\'s attack 3, if provided (applies to monster attacks only) |
'
+ +' ^^monsterCritHit^^ | Resolves to the critical hit dice roll value of the creature (applies to monster/creature attacks only) |
'
+ +' ^^monsterCritMiss^^ | Resolves to the critical miss dice roll value of the creature (applies to monster/creature attacks only) |
'
+ +' ^^monsterDmgMacroSM^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Monster Ability damage Macro |
'
+ +' ^^monsterDmgMacroL^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Monster Ability damage Macro |
'
+ +' ^^monsterDmgMacro1^^ or ^^monsterDmgMacro2^^ or ^^monsterDmgMacro3^^ | Legacy values. Resolve to the same damage Macro call as ^^monsterDmgMacroSM^^ |
'
+ +' ^^monsterDmgSM^^ or ^^ monsterDmgMacroL^^ | Depending on if the Player chose for Roll20 to roll the damage dice or to roll their own dice, resolves to one of (a) the damage dice specification for the selected Monster attack, or (b) a Roll Query requesting the Player to enter a dice roll result. Currently both SM and L resolve the same |
'
+ +' ^^monsterDmg1^^ or ^^monsterDmg2^^ or ^^monsterDmg3^^ | Legacy values. Resolve to the same as ^^monsterDmgSM |
'
+ +'
'
+ +'
'
+ +'
'
+ +' '
+ +' Melee Weapon Attack Templates |
---|
'
+ +'
'
+ +' ^^weapon^^ | Resolves to the name of the weapon |
'
+ +' ^^weapAttkAdj^^ | Resolves to the magical attack adjustment of the weapon |
'
+ +' ^^weapStyleAdj^^ | Resolves to the fighting style attack adjustment of the weapon |
'
+ +' ^^weapStrHit^^ | Resolves to a 1 if the character\'s strength to-hit bonus applies to this weapon, or 0 otherwise |
'
+ +' ^^profPenalty^^ | Resolves to any proficiency penalty incurred by the attacking character for using a non-proficient or related weapon, or 0 if is proficient |
'
+ +' ^^specProf^^ | Resolves to 1 if the attacking character is a specialist in the weapon, otherwise 0 |
'
+ +' ^^masterProf^^ | Resolves to 1 if the attacking character is a master (double specialised) in the weapon, otherwise 0 |
'
+ +' ^^raceBonus^^ | Resolves to the race bonus of the attacking character with this weapon |
'
+ +' ^^twoWeapPenalty^^ | Resolves to any penalty relevant if the attacking character is using two weapons to attack, adjusted by any relevant Fighting Style benefit (is 0 for character classes that can use two weapons without penalty, such as rangers) |
'
+ +' ^^weapDmgAdj^^ | Resolves to the magical damage adjustment of the weapon |
'
+ +' ^^weapStyleDmgAdj^^ | Resolves to any fighting style damage bonus |
'
+ +' ^^magicDmgAdj^^ | Resolves to any magical effect damage bonus or penalty resulting from magic currently in effect |
'
+ +' ^^backstab^^ | Resolves to a 1 if a backstab is being attempted, otherwise 0 |
'
+ +' ^^rogueLevel^^ | Resolves to the Rogue class level of the attacking character (0 if not a Rogue) |
'
+ +' ^^weapCritHit^^ | Resolves to the critical hit dice roll value of the weapon, adjusted by any relevant Fighting Style benefit |
'
+ +' ^^weapCritMiss^^ | Resolves to the critical miss dice roll value of the weapon, adjusted by any relevant Fighting Style benefit |
'
+ +' ^^weapDmgSM^^ | Depending on if the Player chose for Roll20 to roll the damage dice or to roll their own dice, resolves to one of (a) the damage dice specification vs. Medium and smaller opponents for the weapon, or (b) a Roll Query requesting the Player to enter a dice roll result |
'
+ +' ^^weapStyleDmgSM^^ | Resolves to any Fighting Style damage bonus when doing damage to a Medium or smaller opponent |
'
+ +' ^^weapDmgL^^ | Depending on if the Player chose for Roll20 to roll the damage dice or to roll their own dice, resolves to one of (a) the damage dice specification vs. Large and larger opponents for the weapon, or (b) a Roll Query requesting the Player to enter a dice roll result |
'
+ +' ^^weapStyleDmgL^^ | Resolves to any Fighting Style damage bonus when doing damage to a Large or larger opponent |
'
+ +' ^^weapStrDmg^^ | Resolves to a 1 if the character\'s strength damage bonus applies to this weapon, or 0 otherwise |
'
+ +' ^^mwSMdmgMacro^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Melee weapon Ability damage Macro against Medium and smaller opponents |
'
+ +' ^^mwLHdmgMacro^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Melee weapon Ability damage Macro against Large and larger opponents |
'
+ +'
'
+ +'
'
+ +'
'
+ +' '
+ +' Ranged Weapon Attack Templates |
---|
'
+ +'
'
+ +' ^^weapon^^ | Resolves to the name of the weapon |
'
+ +' ^^weapAttkAdj^^ | Resolves to the magical attack adjustment of the ranged weapon. Normally 0 as plus is often on the ammo |
'
+ +' ^^weapStyleAdj^^ | Resolves to the Fighting Style attack adjustment of the weapon |
'
+ +' ^^dexMissile^^ | Resolves to the dexterity missile adjustment of the attacking character |
'
+ +' ^^weapDexBonus^^ | Resolves to a 1 if the dexterity missile bonus applies to the weapon, otherwise 0 |
'
+ +' ^^strAttkBonus^^ | Resolves to the strength to-hit bonus/penalty of the attacking character |
'
+ +' ^^weapStrHit^^ | Resolves to a 1 if the character\'s strength to-hit bonus applies to this weapon, or 0 otherwise |
'
+ +' ^^profPenalty^^ | Resolves to any proficiency penalty incurred by the attacking character for using a non-proficient or related weapon, or 0 if proficient |
'
+ +' ^^specProf^^ | Resolves to 1 if the attacking character is a specialist in the weapon, otherwise 0 |
'
+ +' ^^masterProf^^ | Resolves to 1 if the attacking character is a master (double specialised) in the weapon, otherwise 0 |
'
+ +' ^^raceBonus^^ | Resolves to the race bonus of the attacking character with this weapon |
'
+ +' ^^twoWeapPenalty^^ | Resolves to any penalty relevant if the attacking character is using two weapons to attack, adjusted by any relevant Fighting Style benefit (is 0 for character classes that can use two weapons without penalty, such as rangers) |
'
+ +' ^^weapDmgAdj^^ | Resolves to the magical damage adjustment of the weapon |
'
+ +' ^^rangeMod^^ | Resolves to the range attack modifier, as modified by any valid fighting style |
'
+ +' ^^rangeN^^ | Resolves to 1 if the range is "Near", otherwise 0 |
'
+ +' ^^rangePB^^ | Resolves to 1 if the range is "Point Blank", otherwise 0 |
'
+ +' ^^rangeS^^ | Resolves to 1 if the range is "Short", otherwise 0 |
'
+ +' ^^rangeM^^ | Resolves to 1 if the range is "Medium", otherwise 0 |
'
+ +' ^^rangeL^^ | Resolves to 1 if the range is "Long", otherwise 0 |
'
+ +' ^^rangeF^^ | Resolves to 1 if the range is "Far", otherwise 0 |
'
+ +' ^^rangeSMLF^^ | Resolves to 1 if the range is not "Near" or "Point Blank", otherwise 0 |
'
+ +' ^^ammoDmgAdj^^ | Resolves to the magical damage adjustment of the selected ammunition of the ranged weapon |
'
+ +' ^^ammoStyleDmgAdj^^ | Resolves to the fighting style damage adjustment of the ranged weapon |
'
+ +' ^^magicDmgAdj^^ | Resolves to any magical effect damage bonus or penalty resulting from magic currently in effect |
'
+ +' ^^strDmgBonus^^ | Resolves to the strength damage bonus/penalty of the attacking character |
'
+ +' ^^weapCritHit^^ | Resolves to the critical hit dice roll value of the weapon, as modified by any valid fighting style |
'
+ +' ^^weapCritMiss^^ | Resolves to the critical miss dice roll value of the weapon, as modified by any valid fighting style |
'
+ +' ^^ACvsNoModsMissile^^ | Resolves to the targeted Armour Class vs missiles macro call @{target|Select Target|ACmissile-field} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^ACvsSlashMissile^^ | Resolves to the targeted Slashing damage Armour Class vs missiles macro call @{target|Select Target|SlashACmissile-field} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^ACvsPierceMissile^^ | Resolves to the targeted Piercing Armour Class vs missiles macro call @{target|Select Target|PierceACmissile-field} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^ACvsBludgeonMissile^^ | Resolves to the targeted Bludgeoning Armour Class vs missiles macro call @{target|Select Target|BludgeonACmissile-field} vs. a targeted opponent (only used in targeted attacks) |
'
+ +' ^^ACvsNoModsMissileTxt^^ | Resolves to the text "No Mods" |
'
+ +' ^^ACvsSlashMissileTxt^^ | If this is a slashing weapon, resolves to the text "Slash", otherwise resolves to an empty string |
'
+ +' ^^ACvsPierceMissileTxt^^ | If this is a piercing weapon, resolves to the text "Pierce", otherwise resolves to an empty string |
'
+ +' ^^ACvsBludgeonMissileTxt^^ | If this is a bludgeoning weapon, resolves to the text "Bludgeon", otherwise resolves to an empty string |
'
+ +' ^^ACvsSmissileTxt^^ | If this is a slashing weapon, resolves to the text "S", otherwise resolves to an empty string |
'
+ +' ^^ACvsPmissileTxt^^ | If this is a piercing weapon, resolves to the text "P", otherwise resolves to an empty string |
'
+ +' ^^ACvsBmissileTxt^^ | If this is a slashing weapon, resolves to the text "B", otherwise resolves to an empty string |
'
+ +' ^^ammoDmgSM^^ | Depending on if the Player chose for Roll20 to roll the damage dice or to roll their own dice, resolves to one of (a) the damage dice specification vs. Medium and smaller opponents for the ammunition used, or (b) a Roll Query requesting the Player to enter a dice roll result |
'
+ +' ^^ammoStyleDmgSM^^ | Resolves to any Fighting Style damage bonus when doing damage to a Medium or smaller opponent |
'
+ +' ^^ammoDmgL^^ | Depending on if the Player chose for Roll20 to roll the damage dice or to roll their own dice, resolves to one of (a) the damage dice specification vs. Large and larger opponents for the ammunition used, or (b) a Roll Query requesting the Player to enter a dice roll result |
'
+ +' ^^ammoStyleDmgL^^ | Resolves to any Fighting Style damage bonus when doing damage to a Large or larger opponent |
'
+ +' ^^ammoStrDmg^^ | Resolves to a 1 if the character\'s strength damage bonus applies to the selected ammunition, or 0 otherwise |
'
+ +' ^^ammoLeft^^ | Resolves to the quantity of the selected ammunition left after this attack |
'
+ +' ^^rwSMdmgMacro^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Ranged weapon Ability damage Macro against Medium and smaller opponents |
'
+ +' ^^rwLHdmgMacro^^ | Resolves to the correct Ability Macro name to use in an API button or macro call to run the matching Ranged weapon Ability damage Macro against Large and larger opponents |
'
+ +'
'
+ +'
'
+ +'
5. Character (PC & NPC) Attack Templates
'
+ +'
As previously described, the Attacks Database contains Attack Templates as Ability Macro entries. For Characters and NPCs that attack using weapons "in-hand" (see AttackMaster API documentation for information on taking weapons "in-hand"), four standard Attack Templates are required: -ToHit; -DmgSM; -DmgL; and -Targeted-Attk.
'
+ +'
5.1 The "To Hit" Template
'
+ +'
A standard To Hit Attack Template looks like this (the example is for the AD&D2e version):
'
+ +'
MW-ToHit
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ attacks with their ^^weapon^^}}{{subtitle=Melee Attack}}{{Weapon Used=^^weapon^^}}Specs=[MWtoHit,AttackMacro,1d20,Attack]!setattr --silent --charid ^^cid^^ --ac-hit|{{AC Hit=[[([[^^thac0^^]][Thac0]) - ((([[^^weapAttkAdj^^]][Weapon+]) + ([[^^weapStyleAdj^^]][Style+]) + ([[(^^strAttkBonus^^ * ^^weapStrHit^^)]][Strength+]) + ([[^^profPenalty^^]][Prof Penalty] + [[^^specProf^^]][Specialist] + [[^^masterProf^^*3]][Mastery]) + ([[^^raceBonus^^]][Race mod]) + ([[^^magicAttkAdj^^]][Magic hit adj]) + ([[^^twoWeapPenalty^^]][2-weap penalty]))) - ([[^^toHitRoll^^cs>^^weapCritHit^^cf\<^^weapCritMiss^^]][Dice roll]) ]] }}!!!{{Attk Type=^^weapType^^}}{{Dmg S=[Roll](~^^mwSMdmgMacro^^)}}{{Dmg L=[Roll](~^^mwLHdmgMacro^^)}}{{Crit Roll=^^weapCritHit^^}}{{Fumble Roll=^^weapCritMiss^^}}'
+ +'
The four fields in the Specs data are the standard four used in all Specs fields: Entry Type (MWtoHit), Entry Class (AttackMacro), Handedness (in this case replaced by toHit dice roll spec 1d20), and Entry Supertype (Attack). The key field to note here is the ToHit Dice Roll Specification (which replaces the Handedness field). This can be any valid dice roll, and will be used for the ^^toHitRoll^^ template field if the Player selects Roll20 to roll the attack dice.
'
+ +'
This Attack Template is formatted using a Roll20 Roll Template with a type specified using the ^^defaultTemplate^^ template field, but need not be - formatting is up to the creator of the Attack Template. It is important this information is displayed to the right people - Players that control a character, all Players as a public post, or just the DM for attacks by creatures & NPCs. The ^^toWhoPublic^^ template field will check if the attacking token represents a Character/NPC/Creature controlled by a Player and, if so, make a public post that all can see, but otherwise just whisper the results of the attack to the DM only. Similarly, ^^toWho^^ will whisper the attack information either only to the Player(s) that control the attacking character/creature or, if no one does, then to the DM.
'
+ +'
The rest of the Attack Template defines the calculations using the API supplied data to display the Armour Class value that would be successfully hit by the attacking character, with the selected weapon under the current conditions. It also defines a display of the adjustments that are made to the dice roll which the Players and DM can hover a mouse over to get an explanation of the calculations. All the calculations and tag display are standard Roll20 functionality, so once the Attack Template Data Fields are replaced by actual values by the API and the resulting Ability Macro saved to the attacking character\'s Character Sheet, running it like any other Ability Macro will use only Roll20 functionality, and not involve use of the APIs (unless the Attack template specifically includes an API call).
'
+ +'
The Attack Template shown above is a To Hit template for a Melee weapon attack. That for a Ranged weapon attack is very similar, just using some different and ranged attack related Template Fields.
'
+ +'
5.2 The "Damage" Templates
'
+ +'
There are always two damage Attack Templates to go with each To Hit Template, typically one for damage to Medium and smaller opponents and one for Large and larger. However, as will be seen when discussing the Oil Flask bespoke Attack Templates below, those are not always the outcomes of the two damage Templates. However, they do always start with MW-DmgSM and MW-DmgL for Melee weapon attacks, and RW-DmgSM and RW-DmgL for Ranged weapon attacks (optionally followed by a race, class or weapon name). The standard Damage Attack Template looks like this:
'
+ +'
MW-DmgSM
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ does damage with their ^^weapon^^}}{{Subtitle=Melee Attack}}Specs=[MWtoHit,AttackMacro,1d20,Attack]{{AC Hit=@{^^cname^^|ac-hit}}}{{Attk Type=^^weapType^^}}{{Dmg S=[[ ([[^^weapDmgSM^^]][Dice Roll]) + ([[^^strDmgBonus^^*^^weapStrDmg^^]][Strength+]) + ([[^^weapDmgAdj^^]][Weapon+]) + ([[^^weapStyleDmgAdj^^+^^weapStyleDmgSM^^]][Style+]) + ([[^^magicDmgAdj^^]][Magic dmg adj]) + ([[^^specProf^^*2]][Specialist+] + [[^^masterProf^^*3]][Mastery+])]]}}{{Dmg L=[Roll](~^^mwLHdmgMacro^^)}}{{Crit Roll=^^weapCritHit^^}}{{Fumble Roll=^^weapCritMiss^^}}
'
+ +'
The damage Attack Template works in the same way as the other Attack Templates as explained above for the ToHit template. While the Specs data includes the "To Hit" dice roll specification, this is not used in the damage Template, and is irrelevant. That field just needs to hold something, and a dice roll specification is what is expected. Hopefully, the rest of this damage Attack Template is self explanatory.
'
+ +'
6. Monster Attack Templates
'
+ +'
If a creature specified as a Monster on the Character Sheet uses in-hand weapons, as supported under the RPGMaster APIs, attacks with those weapons (Melee or Ranged) will use the standard To Hit and Damage Attack Templates described above. However, attacks by creatures that are specified as Monsters (e.g. on the Monster tab of the Advanced 2nd Edition character sheet) are generally much simpler than character attacks with in-hand weapons. The differences mean that such creatures require different Attack Templates. Attacks specified on the Monster tab use the Monster Attack Templates: Mon-Attk, Mon-DmgSM, and Mon-DmgL (or the Targeted Attack Templates, see later). Remember that the AttackMaster API supports an extension of the Monster Attk fields on the Advanced 2nd Edition Character Sheet: each can contain a comma-separated list consisting of "attack name","dice roll","speed in segments","damage type" (see AttackMaster Help for details).
'
+ +'
The Monster Attack and Damage Templates look like this:
'
+ +'
Mon-Attk
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ attacks with their ^^attk^^}}{{subtitle=Monster Attack}}{{Weapon Used=^^attk^^}}Specs=[MonAttk,AttackMacro,1d20,Attack]!setattr --silent --charid ^^cid^^ --ac-hit|{{AC Hit=[[([[^^thac0^^]][Thac0]) - ([[^^magicAttkAdj^^]][Magic hit adj]) - ([[^^toHitRoll^^cs\>^^monsterCritHit^^cf\<^^monsterCritMiss^^]][Dice roll]) ]]}}!!!{{Attk Type=^^weapType^^}}{{Dmg S=[Roll](~^^monsterDmgMacroSM^^)}}{{Dmg L=[Roll](~^^monsterDmgMacroL^^)}}{{Crit Roll=^^monsterCritHit^^}}{{Fumble Roll=^^monsterCritMiss^^}}
'
+ +'
'
+ +'
Mon-DmgL
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ does damage with their ^^attk^^}}{{subtitle=Monster Attack}}Specs=[MonRoll,AttackMacro,1d20,Attack]{{AC Hit=[[@{^^cname^^|ac-hit}[AC Hit] ]]}}{{Attk Type=^^weapType^^}}{{Dmg L=[[(([[^^monsterDmg^^]][^^attk^^ Dmg])+([[^^magicDmgAdj^^]][Added Magic Dmg]))]]}}{{Dmg S=[Roll](~^^monsterDmgMacroSM^^)}}{{Crit Roll=^^monsterCritHit^^}}{{Fumble Roll=^^monsterCritMiss^^}}
'
+ +'
Unsurprisingly, these work in exactly the same way as other Attack Templates.
'
+ +'
'
+ +'
7. Targeted Attack Templates
'
+ +'
The AttackMaster API supports the DM (and optionally, Players) using "targeted attacks". This is an attack that prompts the DM / Player to select a target token, and then performs all attack and damage dice rolls at the same time, displaying the attack results alongside the Armour Class and relative health of the targeted opponent. This speeds the attack process even further than having the API do all the attack calculations. Note: the results of the attack are not applied to the targeted opponent - the results are still open to interpretation by the Players and DM, and circumstantial adjustment before manually applying them to the Token / Character Sheet of the opponent.
'
+ +'
The Ranged weapon Targeted Attack Template for AD&D2e (for example) looks like this:
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ attacks @{Target|Select Target|Token_name} with their ^^weapon^^}}{{subtitle=Ranged Attack * **Ammo Left: ^^ammoLeft^^**}}Specs=[RWtargetedAttk,AttackMacro,1d20,Attack]{{AC Hit=[[([[^^thac0^^]][Thac0])-(([[^^weapAttkAdj^^]][Weapon+]) + ([[^^ammoDmgAdj^^]][Ammo+]) + ([[^^weapStyleAdj^^]][Style+]) + ([[ ^^weapDexBonus^^*[[^^dexMissile^^]]]][Dexterity+] )+([[[[^^strAttkBonus^^]]*[[^^weapStrHit^^]]]][Strength+])+([[^^raceBonus^^]][Race mod])+([[^^profPenalty^^]][Prof penalty])+([[^^magicAttkAdj^^]][Magic Hit+])+([[^^twoWeapPenalty^^]][2-weap penalty])+([[^^rangeMod^^]][Range mod]))-([[^^toHitRoll^^cs\>^^weapCritHit^^cf\<^^weapCritMiss^^]][Dice roll]) ]] }}{{Attk Type=^^weapType^^}}{{Target AC=^^targetACmissile^^}}{{Target SAC=^^ACvsSlashMissile^^}}{{Target PAC=^^ACvsPierceMissile^^}}{{Target BAC=^^ACvsBludgeonMissile^^}}{{Dmg S=[[ floor( ([[^^ammoDmgSM^^]][Dice roll]) * ([[(^^rangeN^^*0.5)+(^^rangePB^^*(1+^^masterProfPB^^))+(^^rangeSMLF^^*1)]][Range mult])) + ([[^^rangePB^^*^^masterProfPB^^*2]][Range mod]) + (([[^^ammoDmgAdj^^]][Ammo+])+([[^^ammoStyleDmgAdj^^+^^ammoStyleDmgSM^^]][Style+])+([[^^magicDmgAdj^^]][Magic dmg+]) +([[^^strDmgBonus^^*^^ammoStrDmg^^]][Strength+])) ]]}}{{Dmg L=[[ floor( ([[^^ammoDmgSM^^]][Dice roll]) * ([[(^^rangeN^^*0.5)+(^^rangePB^^*(1+^^masterProfPB^^))+(^^rangeSMLF^^*1)]][Range mult])) + ([[^^rangePB^^*^^masterProfPB^^*2]][Range mod]) + (([[^^ammoDmgAdj^^]][Ammo+])+([[^^ammoStyleDmgAdj^^+^^ammoStyleDmgL^^]][Style+])+([[^^magicDmgAdj^^]][Magic dmg+]) +([[^^strDmgBonus^^*^^ammoStrDmg^^]][Strength+])) ]]}}{{Target HP=^^targetHP^^}}{{Target MaxHP=^^targetMaxHP^^}}{{Target Heart=^^targetHP^^/^^targetMaxHP^^}}{{Crit Roll=^^weapCritHit^^}}{{Fumble Roll=^^weapCritMiss^^}}{{Result=AC Hit\<=Target AC}}
'
+ +'
The key difference, other than doing all of the calculations for the Armour Class hit and both the damage for Medium and smaller and Large and larger, is that several of the Template Fields used resolve to appropriately formatted Roll20 @{target|...} entries, that will display values from the targeted opponent\'s token and/or character sheet. The API searches for the most appropriate token and character sheet fields to resolve the targeted Template Fields to (it searches the attacking creature\'s data, and assumes all tokens are set up the same way): if using the standard RPGMaster token settings (as set by the CommandMaster API --abilities command or [Token Setup] DM\'s Macro button) it will find the data it needs on the token; otherwise it will first search other token fields, then standard Character Sheet character tab fields, then Character Sheet monster tab fields. If the API can\'t find AC or HP data, it will display appropriate text saying the data was not found, but will not cause an error. Thus it is sensible to use these Template Fields rather than statically defined @{target|...} commands.
'
+ +'
'
+ +'
8. Bespoke / Custom Attack Templates
'
+ +'
All of the above examples and discussion have explored the standard Attack Templates distributed with the AttackMaster API. It will be the case that this will cater for around 95% of attacks and attack-like situations (e.g. there is a weapon called "Touch" which Spell Casters can use for touch-attack spells, which uses the standard Attack Templates without change to achieve the needed outcome). However, for that other 5% (or perhaps closer to 1%) of special cases you can define your own bespoke or custom Attack Templates. Being able to change the way attacks are calculated is also essential if you wish to adapt the API to work for game systems other than those for which RPGMaster Library rulesets currently exist.
'
+ +'
As stated in Section 1, you should not add Attack Templates to the Attacks-DB database directly. Instead, create your own Character Sheet named Attack-DB-[any-name-you-want] and add Attack Templates to it. If you want to replace the Attack Templates provided for Melee weapons, Ranged weapons and/or Monster attacks, just create ones in your added database with the same Ability Macro name and they will automatically be used in preference to the standard versions.
'
+ +'
As also mentioned previously, while Attack Templates are always called with names of the format given in Section 3, they do not have to result in standard attacks or damage - the calculations and resulting information provided to players can be whatever is needed as a result of that attack action. An example of this is included in the distributed Attacks-DB, the Oil Flask Attack Template set:
'
+ +'
RW-ToHit-Oil-Flask
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ throws a prepared oil flask}}{{titlebox=transparent}}{{titletext=red; text-shadow: 1px 1px 1px gray}}{{titleimg=https://s3.amazonaws.com/files.d20.io/images/250365814/HB7bJNTar3xasqz7X9W5bg/thumb.png?1634239406}}{{subtitle=Ranged Attack * **Flasks Left: ^^ammoLeft^^**}}{{Weapon Used=Burning Oil Flask}}Specs=[RWtoHitOilFlask,AttackMacro,1d20,Attack]!setattr --silent --charid ^^cid^^ --ac-hit|{{AC Hit=[[([[^^thac0^^]][Thac0])-([[([[^^weapAttkAdj^^]][Weapon+]) + ([[^^weapStyleAdj^^]][Style+]) + ([[^^ammoDmgAdj^^]][Ammo+]) + ([[ ^^weapDexBonus^^*[[^^dexMissile^^]]]][Dexterity+] )+([[[[^^strAttkBonus^^]]*[[^^weapStrHit^^]]]][Strength+])+([[^^raceBonus^^]][Race mod])+([[^^profPenalty^^]][Prof penalty])+([[^^magicAttkAdj^^]][Magic Hit+])+([[^^twoWeapPenalty^^]][2-weap penalty])+([[^^rangeMod^^]][Range mod])]][Adjustments])-([[^^toHitRoll^^cs\>^^weapCritHit^^cf\<^^weapCritMiss^^]][Dice roll]) ]]}}!!!{{Attk Type=^^weapType^^}}{{dmgslabel=Direct Hit}}{{Dmg S=[Hit](~^^rwSMdmgMacro^^)}}{{dmgllabel=Grenade /Splash}}{{Dmg L=[Splash](~^^rwLHdmgMacro^^)}}{{Crit Roll=^^weapCritHit^^}}{{Fumble Roll=^^weapCritMiss^^}}
'
+ +'
The To Hit Attack Template is very similar to a normal Ranged weapon Attack Template, except that instead of API buttons indicating damage rolls vs. different sized opponents, it provides one API button to select a [Direct Hit], and another selecting a [Grenade/Splash] outcome. Each of these still calls the same damage Attack Templates using the Template Fields provided but in this case, because the attack is with a weapon called Oil Flask, the Template Fields will resolve to calls to RW-DmgSM-Oil-Flask and RW-DmgL-Oil-Flask respectively, and these custom Attack Templates do damage in a very different way to a normal Ranged Weapon attack.
'
+ +'
RW-DmgSM-Oil-Flask
'
+ +'
!rounds --aoe @{target|Who\'s the target?|token_id}|circle|feet|0|7|0|fire|true --target single|^^tid^^|@{target|Who\'s the target?|token_id}|Oil-fire|1|-1|Taking fire damage from burning oil|three-leaves
'
+ +'^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ throws a prepared oil flask}}{{TitleBox=transparent}}{{titletext=red; text-shadow: 1px 1px 1px gray}}{{TitleImg=https://s3.amazonaws.com/files.d20.io/images/250365814/HB7bJNTar3xasqz7X9W5bg/thumb.png?1634239406}} {{subtitle=Burning oil * **Flasks Left: ^^ammoLeft^^**}}{{Weapon Used=Burning Oil Flask}}Specs=[RWDmgSMOilFlask,AttackMacro,1d20,Attack]{{AC Hit=[[@{^^cname^^|ac-hit}[AC Hit] ]]}}{{Attk Type=^^weapType^^}}{{DmgSlabel=Fire round 1}}{{Dmg S=[[([[^^ammoDmgSM^^]][Dice Roll])]]}}{{DmgLlabel=Grenade /Splash}}{{Dmg L=[Splash](~^^rwLHdmgMacro^^)}}
'
+ +'
The Oil Flask version of the RW-DmgSM Attack Template caters for damage done by an Oil Flask successfully scoring a direct hit on an opponent. This results in a damage dice roll for this round of 2d6 with no modifiers, and then also makes an API call to the RoundMaster API with two stacked commands: an Area of Effect call to place fire on the opponent\'s token, and a Target call to add a status to the opponent\'s token which will last 2 rounds, causing a Status Effect Macro to run in the second round to prompt for another damage roll of 1d6.
'
+ +'
RW-DmgL-Oil-Flask
'
+ +'
!rounds --aoe ^^tid^^|circle|feet|[[(^^rangeN^^*5)+(^^rangePB^^*10)+(^^rangeS^^*10)+(^^rangeM^^*20)+(^^rangeL^^*30)+(^^rangeF^^*30)-5]]|4|0|fire
'
+ +'^^toWhoPublic^^ &{template:2Egrenademiss} {{name=Prepared Oil Flask}}Specs=[RWDmgLOilFlask,AttackMacro,1d20,Attack]{{aoe=[[3]]}} {{aoesplash=[[3]]}} {{hitdmg=[Hit](~^^rwSMdmgMacro^^)}} {{splashdmg=[Damage](!
/r ^^ammoDmgL^^)}}{{direction=[[1d10]]}} {{distancename=^^range^^}} {{distance=[[(^^rangePB^^+^^rangeS^^)d6+^^rangeM^^d10+(^^rangeL^^*2)d10+(^^rangeF^^*4)d10]]}} {{hit=[[0]]}} {{splash=[[1]]}}
'
+ +'
The Oil Flask version of the RW-DmgL Attack Template caters for an Oil Flask that either missed its intended target, or is deliberately used as a grenade-like missile. This results in a dice roll of 1d3 splash damage to anyone in the area of effect, which is shown using a call to the RoundMaster API Area of Effect command which this time can be positioned where the oil flask landed.
'
+ +'
RW-Targeted-Attk-Oil-Flask
'
+ +'
^^toWhoPublic^^ &{template:^^defaultTemplate^^}{{title=^^tname^^ throws an oil flask at @{Target|Select Target|Token_name} }}{{titlebox=transparent}}{{titletext=red; text-shadow: 1px 1px 1px gray}}{{titleimg=https://s3.amazonaws.com/files.d20.io/images/250365814/HB7bJNTar3xasqz7X9W5bg/thumb.png?1634239406}}{{subtitle=Ranged Attack * **Flasks Left: ^^ammoLeft^^**}}Specs=[RWtargetedOilFlask,AttackMacro,1d20,Attack]{{AC Hit=[[([[^^thac0^^]][Thac0])-(([[^^weapAttkAdj^^]][Weapon+]) + ([[^^weapStyleAdj^^]][Style+]) + ([[^^ammoDmgAdj^^]][Ammo+]) + ([[ ^^weapDexBonus^^*[[^^dexMissile^^]]]][Dexterity+] )+([[[[^^strAttkBonus^^]]*[[^^weapStrHit^^]]]][Strength+])+([[^^raceBonus^^]][Race mod])+([[^^profPenalty^^]][Prof penalty])+([[^^magicAttkAdj^^]][Magic Hit+])+([[^^twoWeapPenalty^^]][2-weap penalty])+([[^^rangeMod^^]][Range mod]))-([[^^toHitRoll^^cs\>^^weapCritHit^^cf\<^^weapCritMiss^^]][Dice roll]) ]] }}{{Attk Type=^^weapType^^}}{{Target AC=^^targetACmissile^^}}{{Target SAC=^^ACvsSlashMissile^^}}{{Target PAC=^^ACvsPierceMissile^^}}{{Target BAC=^^ACvsBludgeonMissile^^}}{{DmgSlabel=Direct Hit}}{{Dmg S=[Hit](~^^rwSMdmgMacro^^)}}{{DmgLlabel=Grenade /Splash}}{{Dmg L=[Splash](~^^rwLHdmgMacro^^)}}{{Target HP=^^targetHP^^}}{{Target MaxHP=^^targetMaxHP^^}}{{Target Heart=^^targetHP^^/^^targetMaxHP^^}}{{Crit Roll=^^weapCritHit^^}}{{Fumble Roll=^^weapCritMiss^^}}{{Result=AC Hit<=Target AC}}
'
+ +'
The Oil Flask version of the RW-Targeted-Attk Attack Template combines the functions and calculations of the other Oil Flask custom Attack Templates in a single result display, with appropriate API buttons to implement the various outcomes of the attack.
'
+ +'
Similar or entirely different custom Attack Templates can be created for other individual weapons with non-standard attack outcomes, or for individual classes of character, creatures, or races. Just use the Attack Template naming conventions described in Section 3, and add them to your own Attack Databases as described in Section 1, and you can give Players more interesting situations and means of dealing with them. When combined with the features and capabilities of the RoundMaster API and other APIs of the RPGMaster suite, the possibilities are endless!
'
+ +'
',
+ },
+ StylesDB_Handout: {name:'Fighting Styles Database Help',
+ version:1.02,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Fighting Styles Database Help v1.02'
+ +'
'
+ +''
+ +'
Fighting Styles Database
'
+ +'
for AttackMaster v1.3.05 and later
'
+ +'
1. General Database information
'
+ +'
The RPGMaster APIs use a number of databases to hold Ability Macros defining rules, conditions and benefits of various styles of fighting with weapons and shields, defined in the RPGMaster Library for various game versions. Databases supplied with the APIs are held internally to the APIs. However, the AttackMaster or MagicMaster API command --extract-db can be used to extract any or all standard databases to Character Sheets for examination and update. DMs can add their own fighting style definitions to additional databases held as Character Sheets. Additional databases should be named as follows:
'
+ +'
Fighting Styles: | additional databases: Styles-DB-[added name] where [added name] can be replaced with anything you want. |
'
+ +'
However: 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. Styles-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.
'
+ +'
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.
'
+ +'
Important Note: all Character Sheet databases must have their \'ControlledBy\' value (found under the [Edit] button at the top right of each sheet) set to \'All Players\'. 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.
'
+ +'
Important Note: databases extracted using the --extract-db command will be able to be edited, but will also slow the system down - the versions held internally in the APIs are much faster for the system to access. Once any extracted database has been examined, it is best to delete them and use the --check-db to re-index the databases so the system operates as fast as possible.
'
+ +'
Each database has a similar structure, with:
'
+ +'
- Ability Macros named as the fighting style specified, and used to describe and provide specifications for using the commands with the AttackMaster API;
'
+ +'- Custom Attributes with the attribute name "ct-ability-macro-name", one per Ability Macro, which defines the speed and type for each item;
'
+ +'- An entry in a list on the character sheet in the spell book of the relevant Character Sheet tab (various spell books for different items - see entry below);
'
+ +'- Optionally, some entries come also with attributes that define Powers and Spells delivered by or stored on the item (irrelevant for fighting styles).
'
+ +'
Note: a DM only needs to program the Ability Macro using the formats shown in the next section, and then run the !attk --check-db or !magic --check-db command, which will correctly parse the ability macro and set the rest of the database entries as needed.
'
+ +'
Ability Macros can be whatever the DM wants and can be as simple or as complex as desired, as long as they include the required information specified below. Roll Templates are very useful when defining ability macros - the RPGMaster Library provides several new Roll Templates that do not rely on any particular Character Sheet: RPGMdefault is the most relevant. See the RPGMaster Library help handout for further information. When a Player or an NPC or Monster views the specifications of a fighting style the APIs run the relevant Ability Macro from the database as if it had been run by the Player from the chat window. All Roll20 functions for macros are available.
'
+ +'
1.1 Replacing Provided Styles
'
+ +'
If you want to replace any style provided in 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.
'
+ +'
2. Fighting Style Databases
'
+ +'
Fighting style databases have names that start with Styles-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.
'
+ +'
As previously stated, each style definition has 3 (or 4) parts in the database (see Section 1): an Ability Macro with a name that is unique and matches the style, an Attribute with the name of the Ability Macro preceded by "ct-", a listing in the database character sheet of the ability macro name separated by \'|\' along with other fighting styles. 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).
'
+ +'
Note: The DM creating new weapons does not need to worry about anything other than the Ability Macro in the database, as running the AttackMaster or MagicMaster -check-db Styles-DB command will update all other aspects of the database appropriately for all databases that have a name starting with or including \'Styles-DB\', as long as the Specs and Data fields are correctly defined. Running the command -check-db with no parameters will check and update all databases.
'
+ +'
The Styles-DB database provided with the APIs contains standard definitions for the four fighting styles defined in The Complete Fighter\'s Handbook, plus a couple of other examples for Ranged weapons to demonstrate how other styles can be defined. After extracting the provided Styles database or creating your own as discussed above, aAbility macros can be added to a database just by using the [+Add] button at the top of the Abilities column in the Attributes and Abilities 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 Centre for more information.
'
+ +'
Here is an example:
'
+ +'
Weapon & Shield Style
'
+ +'
&{template:RPGMdefault}{{name=Two Weapon Fighting Style}}Specs=[Two Weapon,Style,2H,Melee-Style]{{desc=With this popular style, the fighter has a weapon in each hand—usually a longer weapon in his good hand and a shorter one in his off-hand. Unless the character has Style Specialization in this style, the second (off-hand) weapon must be shorter than the primary weapon.}}StyleData=[prime:melee, offhand:melee, t:any, st:any],[twp:0.2],[twp:0.2]{{desc1=**Advantages**
'
+ +'One great advantage to this style is that you always have another weapon in hand if you drop or lose one. A single Disarm maneuver cannot rid you of your weapons.}}{{desc2=**Disadvantages**
'
+ +'The principal disadvantage to this style, as with some other styles, is that you don\'t gain the AC benefit of a shield.}}{{desc3=**Style Specialization**
'
+ +'Please read the "Attacking with Two Weapons" section from the Player\'s Handbook, page 96, before continuing.
'
+ +'If you devote a weapon proficiency slot to style specialization with Two-Weapon Style, you get two important benefits. First, your attack penalty drops; before, it was a –2 with your primary weapon and –4 with your secondary, but with Specialization in Two-Weapon Style it becomes 0 with your primary weapon and a –2 with your secondary weapon. (If you\'re already ambidextrous, that penalty is 0 with primary weapon and 0 with secondary weapon). Second, you\'re allowed to use weapons of the same length in each hand, so you can, for example, wield two long swords.
'
+ +'When fighting with two-weapon technique, you can choose for both weapons to try the same maneuver (for example, two strikes, or two disarms), or can have each try a different maneuver (one strike and one parry, one pin and one strike). If the two maneuvers are to be different, each receives a –1 attack penalty.
'
+ +'Though rangers don\'t suffer the off-hand penalties for two-weapons use, they do not get a bonus to attack rolls if they devote a weapon proficiency slot to Two-Weapon Style. They do get the other benefit, of being able to use weapons of equal length.}}
'
+ +'
The ability specification for the Weapon & Shield Fighting Style uses a Roll20 Roll Template, in this case defined in the RPGMaster Library (see the help handout for the Library to review the specifications of this template), but any Roll Template you desire can be used. The entries in the Roll Template itself can be anything you desire, giving as much or as little information as you want. However, the important elements for the APIs are those highlighted. Each of these elements are inserted between the elements of the Roll Template, meaning they will not be seen by the player when the macro is run. Generally spaces, hyphens and underscores in the data elements are ignored, and case is not significant. Each element is described below:
'
+ +'
Specs = [Type, Spec Class, Handedness, Style Group]
'
+ +'
The Specs section describes what style type and proficiency groups this weapon belongs to. These fields must be in this order. This format is identical for all database items, whether in these databases or others used by the Master series of APIs.
'
+ +'
Type | is the type of the style, often similar to the ability macro name. |
'
+ +'Spec Class | is always Style for entries in the Styles database. |
'
+ +'Handedness | is #H, where # is the number of hands needed to engage in this fighting style. |
'
+ +'Style Group | is the group of related fighting styles that the style belongs to, which currently can be Melee Style or Ranged Style. Further Style Groups related to other forms of combat may be introduced in the future. |
'
+ +'
StyleData=[prime:melee, offhand:shield|melee, t:any, st:any],[shattk:+1],[shattk:+1,twp:0.2]
'
+ +'
The StyleData section specifies the data relating to the style rules for which types of weapon need to be wielded in which hands, and the benefits then achieved if either Proficient in the Style, or a Specialist in the Style. The first set of brackets enclose the preconditions for the style to be valid given what the character has in-hand (as equipped using the attk menu / change weapon menu). The second set specify the benefits to be implemented if the style is valid and the character is proficient in the style, and the third set specify the benefits from being a specialist (as set by the token-setup / Add to Proficiences menu). These fields can be in any order.
'
+ +'
prime: | Nothing in hand | The class of weapon or item that must be being held in the Primary hand for this Style to be effective: one or more of spell, melee, ranged, shield, and throwing. Can be a multi-class item, such as a weapon defined as melee|ranged for a weapon that can be used both as a melee and a ranged weapon (e.g. a warhammer) |
'
+ +'offhand: | Nothing in hand | The class of weapon or item that must be being held in the Offhand hand for this Style to be effective (classes as for Primary hand). Can be a multi-class item, as described for the Primary hand. In this case shield|melee is specified, meaning a shield that can be used to punch or parry as a weapon. |
'
+ +'weaps: | any | The list of weapon/item type(s) or supertype(s) (weapon groups) that are valid to have in-hand for this Style to be effective, separated by verticle bars (\'|\'). If a supertype is specified, all weapons/items of that supertype will be valid. |
'
+ +'shattk: | 0 | The number of additional attacks in a round to grant for a shield punch or parry if the style is valid and proficient at the specified level |
'
+ +'twp: | 2.4 | The Two Weapon Penalty to grant if the style is valid and proficient at the specified level, specified as primary penalty, dot, offhand penalty |
'
+ +'
'
+ +'
Whenever proficiencies for the character are changed using the token-setup / Add to Proficiences menu, or items in-hand are equipped using the Attk menu / Change Weapon menu, the APIs will scan all currently proficient and specialist styles defined for the character, and see if any are valid. If they are, the APIs will automatically apply the benefits to initiative (if using the InitiativeMaster API) and to attacks.
'
+ +'
Additional data fields are available for supporting the rules and benefits of other styles:
'
+ +'
twohand: | Nothing in hand | The class of weapon or item that must be being held in Both Hands or otherwise as a two (or more) handed weapon for this Style to be effective, with the same specification syntax as for the primary weapon above. Note that some one-handed weapons can now be taken in-hand as two-handed weapons using the list under the [Both hands] button when equipping, such as Battle Axe, so that the Two Hander Style can be supported as defined in The Complete Fighter\'s Handbook. This requires the latest Weapon Database to be loaded and not overridden by an old definition in a bespoke database in the campaign. |
'
+ +'ac: | 0 | The Armour Class bonus or penalty granted when the style is active (e.g. as required by the Single Weapon Style) |
'
+ +'mwsp: | 0 | The melee weapon speed bonus or penalty granted when the style is active (e.g. as required by the Two Hander Style). Negative numbers improve speed, positive numbers worsen it. |
'
+ +'rwsp: | 0 | The ranged weapon speed bonus or penalty granted when the style is active. Negative numbers improve speed, positive worsen speed. |
'
+ +'mwn: | 0 | The number of attacks per round to increase (or decrease) a melee weapon by when the style is active. Can be fractions expressed as e.g. 1/2 for one additional attack every 2 rounds. Negative numbers reduce attacks per round. |
'
+ +'rwn: | 0 | Same as for mwn, but for ranged weapons. |
'
+ +'mwadj: | 0 | Melee weapon To-hit bonus or penalty granted when the style is active. Positive numbers are beneficial. |
'
+ +'rwadj: | 0 | Ranged weapon To-hit bonus or penalty granted when the style is active. Positive numbers are beneficial. |
'
+ +'mwch: | 20 | Melee weapon Critical Hit value to set when the style is active. |
'
+ +'rwch: | 20 | Ranged weapon Critical Hit value to set when the style is active. |
'
+ +'mwcm: | 1 | Melee weapon Critical Miss value to set when the style is active. |
'
+ +'rwcm: | 1 | Ranged weapon Critical Miss value to set when the style is active. |
'
+ +'rwr: | \'\' | Adjusts the ranges of Ranged Weapons when the style is active. Format is [=][+/-]#/[+/-]#/[+/-]#/[+/-]# where each number adjusts ranges in the order Point Blank/Short/Medium/Long. If Point Blank range is irrelevant for a particular ranged weapon, the first number is ignored. Positive numbers increase range. If \'=\' is specified as the first character, the range is set to be that specified, rather than adjusted by it. |
'
+ +'rwrm: | \'\' | The bonuses or penalties applied at different ranges for ranged weapons when the style is active. Uses the format N=[+/-]#|PB=[+/-]#|S=[+/-]#|M=[+/-]#|L=[+/-]#|F=[+/-]# where each value will be added to the standard range bonuses/penalties. |
'
+ +'dmg: | 0 | The melee weapon damage benefit or penalty applied to any opponent when the style is active. |
'
+ +'dmgsm: | 0 | The melee weapon damage benefit or penalty applied to Medium sized and smaller opponents when the style is active. |
'
+ +'dmgl: | 0 | The melee weapon damage benefit or penalty applied to Large and larger opponents when the style is active. |
'
+ +'ammoadj: | 0 | The ranged weapon ammo damage benefit or penalty applied to all opponents when the style is active. |
'
+ +'ammosm: | 0 | The ranged weapon ammo damage benefit or penalty applied to Medium sized and smaller opponents when the style is active. |
'
+ +'ammol: | 0 | The ranged weapon ammo damage benefit or penalty applied to Large and larger opponents when the style is active. |
'
+ +'oneh: | \'\' | A specification using any of the above fields for benefits to be applied to one-handed weapons only. The format of the specification is oneh:key=value|key=value|... e.g. oneh:dmg=+1|mwn=1/2, |
'
+ +'twoh: | \'\' | A specification using any of the above fields for benefits to be applied to two-handed weapons only. The format of the specification is the same as for oneh |
'
+ +'
'
+ +'
'
+ +'
Here is another example showing how the keys oneh and twoh are used in combination with other keys to implement the Two-Hander Style:
'
+ +'
Two-Hander Style
'
+ +'
&{template:RPGMdefault}{{name=Two Hander Fighting Style}}Specs=[Two Hander,Style,2H,Melee-style]{{desc=Two-Hander Style involves carrying and wielding a weapon with both hands. Naturally, many weapons (including polearms, the great axe, the two-handed sword, and others) require two-handed technique. Other weapons (such as bastard sword, javelin, and spear) have it as a listed option.}}StyleData=[twohand:melee, weaps:any],[1H:dmg=+1, 2H:mwsp=-3],[1H:dmg=+1, 2H:mwsp=-3]{{desc1=**Advantages**
'
+ +'The main advantage of two-handed weapon technique is that it allows the character to wield large two-handed weapons which can do substantial amounts of damage.
'
+ +'A second advantage is that, if you are using a two-handed weapon, the Disarm maneuver is only of partial use against you. A single successful Disarm against a two-handed weapon user won\'t knock the weapon out of the wielder\'s hands; it will merely knock his weapon askew and make him take some time to recover, so he automatically loses initiative on his next round. However, two Disarm maneuvers successfully made against the character in the same round will knock the weapon loose.}}{{desc2=**Disadvantages**
'
+ +'As with single-weapon use, two-handed weapon technique has the drawback that the user cannot wear or use a shield, or gain the shield\'s AC bonus.}}{{desc3=**Style Specialization**
'
+ +'You can, by devoting a weapon proficiency to it, take a Style Specialization with Two-Hander Style.
'
+ +'Style Specialization with Two-Hander Style gives you a very specific benefit: When you\'re using a weapon two-handed, that weapon\'s Speed Factor is reduced by 3.
'
+ +'This is because when a fighter wields such a weapon with both hands on the hilt, he has more leverage on the blade and can move it faster. That\'s what Style Specialization in Two-Hander Style will do for the character: It teaches him how to use the weapon much faster and more aggressively than someone with less specialized training in the weapon.}}{{desc4=**One-Handed Weapons Used Two-Handed**
'
+ +'Some players don\'t realize that many other one-handed weapons can also be used two-handed. If you specialize in Two-Hander Style and then use a one-handed weapon in two hands, you also get a bonus of +1 to damage. The one-handed weapons which can be used two-handed in this fashion include: Battle axe, Club, Footman\'s flail, Footman\'s pick, Horseman\'s flail, Horseman\'s mace, Horseman\'s pick, Morning star, Long sword, Warhammer.}}
'
+ +'
Here the data specification is:
'
+ +'
StyleData=[twohand:melee, weaps:any],[1H:dmg=+1, 2H:mwsp=-3],[1H:dmg=+1, 2H:mwsp=-3]
'
+ +'
This specifies that there must be a melee weapon equipped in the [Both Hands] slot, and if this is a two-handed weapon then the melee weapon speed is improved by 3 segments. However, if the weapon in the [Both Hands] slot is one of the few one-handed weapons allowed to be taken in both hands (as defined in The Complete Fighter\'s Handbook for this style), then instead it will gain +1 to the damage it inflicts. In this case, the same benefits apply whether the character is just proficient or specialist in the Two-Hander Style.
'
+ +'
Note: only cetain one-handed weapons can be taken in both hands. Indeed, only certain one-handd weapons will appear in the weapon list shown when the [Both Hands] button is selected on the Change Weapon menu. This is achieved in the weapon specifications in the Weapons Database. For full details, see the explanation given in the Weapons & Armour Database Help handout. In summary, a one-handed weapon which can be wielded two-handed and gain Two-Hander Fighting Style benefits, such as a Battle Axe, requires a second Specs dataset with the \'2H\' attribute, but no additional ToHitData datasets. This informs the APIs that this weapon can be taken in both hands, but will not gain any benefits from doing so (unlike, e.g. a Bastard Sword) unless the Character has proficiency in the Two-Hander Fighting Style.
'
+ +'
Other styles can be defined that are not specified in The Complete Fighter\'s Handbook, and some examples are provided in the distributed database:
'
+ +'
Bowyer Style
'
+ +'
&{template:RPGMdefault}{{name=Bowyer Fighting Style}}Specs=[Bowyer,Style,2H,Ranged-style]{{desc=Bowyer Fighting Style reflects fighters who practice day in, day out at the range perfecting their use of bows of all types.}}StyleData=[twohand:ranged, weaps:bow],[rwr:+1/+1/+2/+3,rwsp:-2],[rwr:+1/+1/+3/+5,rwsp:-3,rwn:+1/2]{{desc1=**Advantages**
'
+ +'The main advantage of bowyer technique is that it allows the character to wield two-handed bows which can do damage at long ranges, staying out of melee and making you a difficult enemy to attack.}}{{desc2=**Disadvantages**
'
+ +'As with any two-handed weapon use use, bowyer weapon technique has the drawback that the user cannot wear or use a shield, or gain the shield\'s AC bonus.}}{{desc3=**Style Specialization**
'
+ +'You can, by devoting a weapon proficiency to it, take a Style Specialization with Bowyer Style.
'
+ +'Style Specialization with Bowyer Style enables you to extend your accuracy at range by 10 yards at short range, 20 at medium and 30 at long range, and improve the speed of the bow by 2 segments. As their skill improves further (by dedicating two proficiency slots), range increases further (by 30 yards at medium and 50 at long), and nocking arrows and drawing the bow faster to enable them to get additional attack every other round}}
'
+ +'
This style has a slightly more complex data specification:
'
+ +'
StyleData=[twohand:ranged, weaps:bow],[rwr:+1/+1/+2/+3,rwsp:-2],[rwr:+1/+1/+3/+5,rwsp:-3,rwn:+1/2]
'
+ +'
You can see here the application of the restriction of this fighting style to two-handed ranged weapons that belong to the weapon group bow, then applying benefits using the range extension key rwr, the ranged weapon speed modifier rwsp, and improving the number of attacks for a ranged weapon by one attack per two rounds using rwn.
'
+ +'
A wide range of fighting styles can be created using the different combination of rules and benefits, to enrich the game you create, and your players experience. If you need help or guidance, or experience any issues, do access the RPGMaster forum on Roll20 - search the wiki for the link, or navigate via the Community Forums to the API / Mods forum and search for RPGMaster.
'
+ }
+ });
+
+ const fieldGroups = Object.freeze({
+ MELEE: {prefix:'MW_', tableDef:fields.MW_table},
+ DMG: {prefix:'Dmg_', tableDef:fields.Dmg_table},
+ RANGED: {prefix:'RW_', tableDef:fields.RW_table},
+ AMMO: {prefix:'Ammo_', tableDef:fields.Ammo_table},
+ WPROF: {prefix:'WP_', tableDef:fields.WP_table},
+ MI: {prefix:'Items_', tableDef:fields.Items_table},
+ MAGIC: {prefix:'Magic_', tableDef:fields.Magic_table},
+ SPELLS: {prefix:'Spells_', tableDef:fields.Spells_table},
+ POWERS: {prefix:'Powers_', tableDef:fields.Powers_table},
+ INHAND: {prefix:'InHand_', tableDef:fields.InHand_table},
+ QUIVER: {prefix:'Quiver_', tableDef:fields.Quiver_table},
+ STYLES: {prefix:'Style_', tableDef:fields.Style_table},
+ GEAR: {prefix:'Gear_', tableDef:fields.Gear_table},
+ STORED: {prefix:'StoredGear_', tableDef:fields.StoredGear_table},
+ DUSTS: {prefix:'Dusts_', tableDef:fields.Dusts_table},
+ SCROLLS:{prefix:'Scrolls_', tableDef:fields.Scrolls_table},
+ MONWEAP:{prefix:'MonWeap_', tableDef:fields.MonWeap_table},
+ ALTWIZ: {prefix:'AltWizSpells_',tableDef:fields.AltWizSpells_table},
+ ALTPRI: {prefix:'AltPriSpells_',tableDef:fields.AltPriSpells_table},
+ });
+ const miTypeLists = Object.freeze({
+ miscellaneous: {type:'miscellaneous',field:fields.ItemMiscList},
+ protectioncloak:{type:'miscellaneous',field:fields.ItemMiscList},
+ protectionboots:{type:'miscellaneous',field:fields.ItemMiscList},
+ light: {type:'miscellaneous',field:fields.ItemMiscList},
+ weapon: {type:'weapon',field:fields.ItemWeaponList},
+ melee: {type:'weapon',field:fields.ItemWeaponList},
+ innatemelee: {type:'weapon',field:fields.ItemWeaponList},
+ ranged: {type:'weapon',field:fields.ItemWeaponList},
+ innateranged: {type:'weapon',field:fields.ItemWeaponList},
+ ammo: {type:'ammo',field:fields.ItemWeaponList},
+ armor: {type:'armour',field:fields.ItemArmourList},
+ armour: {type:'armour',field:fields.ItemArmourList},
+ totalac: {type:'armour',field:fields.ItemArmourList},
+ shield: {type:'armour',field:fields.ItemArmourList},
+ helm: {type:'armour',field:fields.ItemArmourList},
+ ring: {type:'ring',field:fields.ItemRingList},
+ protectionring: {type:'ring',field:fields.ItemRingList},
+ potion: {type:'potion',field:fields.ItemPotionList},
+ scroll: {type:'scroll',field:fields.ItemScrollList},
+ scrollcase: {type:'scroll',field:fields.ItemScrollList},
+ rod: {type:'rod',field:fields.ItemWandsList},
+ staff: {type:'rod',field:fields.ItemWandsList},
+ wand: {type:'rod',field:fields.ItemWandsList},
+ magic: {type:'rod',field:fields.ItemWandsList},
+ dmitem: {type:'dmitem',field:fields.ItemDMList},
+ attackmacro: {type:'attack',field:fields.ItemAttacksList},
+ style: {type:'style',field:fields.ItemWeaponList},
+ });
+ const clTypeLists = Object.freeze({
+ warriorclass: {type:'warrior',field:fields.ClassWarriorList},
+ warriorhrclass: {type:'warrior',field:fields.ClassWarriorList},
+ warriorkitclass:{type:'warrior',field:fields.ClassWarriorList},
+ wizardclass: {type:'wizard',field:fields.ClassWizardList},
+ wizardhrclass: {type:'wizard',field:fields.ClassWizardList},
+ wizardkitclass: {type:'wizard',field:fields.ClassWizardList},
+ priestclass: {type:'priest',field:fields.ClassPriestList},
+ priesthrclass: {type:'priest',field:fields.ClassPriestList},
+ priesthoodclass:{type:'priest',field:fields.ClassPriestList},
+ priestkitclass: {type:'priest',field:fields.ClassPriestList},
+ rogueclass: {type:'rogue',field:fields.ClassRogueList},
+ roguehrclass: {type:'rogue',field:fields.ClassRogueList},
+ roguekitclass: {type:'rogue',field:fields.ClassRogueList},
+ psionclass: {type:'psion',field:fields.ClassPsionList},
+ psionhrclass: {type:'psion',field:fields.ClassPsionList},
+ psionkitclass: {type:'psion',field:fields.ClassPsionList},
+ creatureclass: {type:'creature',field:fields.ClassCreatureList},
+ humanoidrace: {type:'humanoid',field:fields.RaceHumanoidList},
+ humanoidhrrace: {type:'humanoid',field:fields.RaceHumanoidList},
+ humanoidkitrace:{type:'humanoid',field:fields.RaceHumanoidList},
+ humanoidcreature:{type:'creature',field:fields.RaceCreatureList},
+ creaturerace: {type:'creature',field:fields.RaceCreatureList},
+ creaturehrrace: {type:'creature',field:fields.RaceCreatureList},
+ creaturekitrace:{type:'creature',field:fields.RaceCreatureList},
+ });
+ const spTypeLists = Object.freeze({
+ muspelll1: {type:'muspelll1',field:['spellmem','current']},
+ muspelll2: {type:'muspelll2',field:['spellmem2','current']},
+ muspelll3: {type:'muspelll3',field:['spellmem3','current']},
+ muspelll4: {type:'muspelll4',field:['spellmem4','current']},
+ muspelll5: {type:'muspelll5',field:['spellmem30','current']},
+ muspelll6: {type:'muspelll6',field:['spellmem5','current']},
+ muspelll7: {type:'muspelll7',field:['spellmem6','current']},
+ muspelll8: {type:'muspelll8',field:['spellmem7','current']},
+ muspelll9: {type:'muspelll9',field:['spellmem8','current']},
+ muspelll0: {type:'muspelll0',field:['spellmem20','current']},
+ prspelll1: {type:'prspelll1',field:['spellmem10','current']},
+ prspelll2: {type:'prspelll2',field:['spellmem11','current']},
+ prspelll3: {type:'prspelll3',field:['spellmem12','current']},
+ prspelll4: {type:'prspelll4',field:['spellmem13','current']},
+ prspelll5: {type:'prspelll5',field:['spellmem14','current']},
+ prspelll6: {type:'prspelll6',field:['spellmem15','current']},
+ prspelll7: {type:'prspelll7',field:['spellmem16','current']},
+ prspelll0: {type:'prspelll0',field:['spellmem17','current']},
+ power: {type:'power', field:['spellmem23','current']},
+ itempower: {type:'itempower',field:['spellmem21','current']},
+ itemspell: {type:'itemspell',field:['spellmem22','current']},
+ melee: {type:'',field:['']},
+ innatemelee: {type:'',field:['']},
+ ranged: {type:'',field:['']},
+ innateranged: {type:'',field:['']},
+ });
+ const primeClasses=['Warrior','Wizard','Priest','Rogue','Psion','Creature'];
+ const classLevels = [
+ [fields.Fighter_class,fields.Fighter_level],
+ [fields.Wizard_class,fields.Wizard_level],
+ [fields.Priest_class,fields.Priest_level],
+ [fields.Rogue_class,fields.Rogue_level],
+ [fields.Psion_class,fields.Psion_level],
+ [fields.Fighter_class,fields.Monster_hitDice]
+ ];
+ const casterLevels = [
+ [fields.Wizard_class,fields.Wizard_level],
+ [fields.Priest_class,fields.Priest_level],
+ [fields.Fighter_class,fields.Fighter_level],
+ [fields.Rogue_class,fields.Rogue_level],
+ [fields.Psion_class,fields.Psion_level],
+ [fields.Fighter_class,fields.Monster_hitDice]
+ ];
+
+ const baseThac0table = [
+ [20,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1],
+ [20,20,20,20,19,19,19,18,18,18,17,17,17,16,16,16,15,15,15,14,14],
+ [20,20,20,20,18,18,18,16,16,16,14,14,14,12,12,12,10,10,10,8,8],
+ [20,20,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11],
+ [20,20,20,19,19,18,18,17,17,16,16,15,15,14,14,13,13,12,12,11,11],
+ ];
+
+ const ordMU =['WIZARD',
+ 'MAGICUSER',
+ 'MAGE',
+ 'MU'];
+
+ var specMU=['ABJURER',
+ 'CONJURER',
+ 'DIVINER',
+ 'ENCHANTER',
+ 'ILLUSIONIST',
+ 'INVOKER',
+ 'NECROMANCER',
+ 'TRANSMUTER'];
+
+ const wisdomSpells=[
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,3,3,3,3,4,4],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2]
+ ];
+ const spellLevels = Object.freeze({
+ mu: [{ spells: 0, base: 0, book: 0 },
+ { spells: 0, base: 1, book: '' },
+ { spells: 0, base: 4, book: 2 },
+ { spells: 0, base: 7, book: 3 },
+ { spells: 0, base: 10, book: 4 },
+ { spells: 0, base: 70, book: 30},
+ { spells: 0, base: 13, book: 5 },
+ { spells: 0, base: 16, book: 6 },
+ { spells: 0, base: 19, book: 7 },
+ { spells: 0, base: 22, book: 8 }],
+ pr: [{ spells: 0, base: 0, book: 0 },
+ { spells: 0, base: 28, book: 10},
+ { spells: 0, base: 31, book: 11},
+ { spells: 0, base: 34, book: 12},
+ { spells: 0, base: 37, book: 13},
+ { spells: 0, base: 40, book: 14},
+ { spells: 0, base: 43, book: 15},
+ { spells: 0, base: 46, book: 16}],
+ pw: [{ spells: 0, base: 0, book: 0 },
+ { spells: 1, base: 67, book: 23}],
+ mi: [{ spells: 0, base: 0, book: 0 },
+ { spells: 0, base: 64, book: 22}],
+ pm: [{ spells: 0, base: 0, book: 0 },
+ { spells: 0, base: 61, book: 21}],
+ });
+
+ var spellsPerLevel = {
+ WIZARD: {MU:[[9,1,100,'MU'],
+ [0,1,2,2,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5],
+ [0,0,0,1,2,2,2,3,3,3,4,4,4,5,5,5,5,5,5,5,5],
+ [0,0,0,0,0,1,2,2,3,3,3,4,4,5,5,5,5,5,5,5,5],
+ [0,0,0,0,0,0,0,1,2,2,2,3,4,4,4,5,5,5,5,5,5],
+ [0,0,0,0,0,0,0,0,0,1,2,3,4,4,4,5,5,5,5,5,5],
+ [0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,3,3,3,3,4],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2],
+ ]},
+ PRIEST: {PR:[[7,1,100,'PR'],
+ [0,1,2,2,3,3,3,3,3,4,4,5,6,6,6,6,7,7,8,9,9],
+ [0,0,0,1,2,3,3,3,3,4,4,4,5,6,6,6,7,7,8,9,9],
+ [0,0,0,0,0,1,2,2,3,3,3,4,5,6,6,6,7,7,8,8,9],
+ [0,0,0,0,0,0,0,1,2,2,3,3,3,4,5,6,6,7,8,8,8],
+ [0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,4,4,5,6,6,7],
+ [0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,3,4,4,5],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,2,2],
+ ]},
+ RANGER: {PR:[[3,8,9,'PR'],
+ [0,0,0,0,0,0,0,0,1,2,2,2,2,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3],
+ ]},
+ PALADIN:{PR:[[4,9,9,'PR'],
+ [0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,3,3,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,3,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,3,3,3,3],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,3],
+ ]},
+ BARD: {MU:[[6,1,100,'MU'],
+ [0,0,1,2,2,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4],
+ [0,0,0,0,1,1,2,2,3,3,3,3,3,3,3,3,3,4,4,4,4],
+ [0,0,0,0,0,0,0,1,1,2,2,3,3,3,3,3,3,3,4,4,4],
+ [0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,3,3,3,3,4,4],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,3,3,4],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3],
+ ]},
+ OTHER: {MU:[[0,0,0,'']],
+ PR:[[0,0,0,'']]},
+ };
+ var defaultNonProfPenalty = [
+ [fields.Fighter_class,fields.Fighter_level,-2],
+ [fields.Wizard_class,fields.Wizard_level,-5],
+ [fields.Priest_class,fields.Priest_level,-3],
+ [fields.Rogue_class,fields.Rogue_level,-3],
+ [fields.Psion_class,fields.Psion_level,-4]
+ ];
+ var rangedWeapMods = {
+ N : -5,
+ PB : 2,
+ S : 0,
+ M : -2,
+ L : -5,
+ F : -20,
+ };
+ var saveLevels = {
+ warrior: [0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9],
+ wizard: [0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5],
+ priest: [0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7],
+ rogue: [0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6],
+ psion: [0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6],
+ creature: [0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9],
+ };
+ var baseSaves = {
+ warrior: [[16,18,17,20,19],[14,16,15,17,17],[13,15,14,16,16],[11,13,12,13,14],[10,12,11,12,13],[8,10,9,9,11],[7,9,8,8,10],[5,7,6,5,8],[4,6,5,4,7],[3,5,4,4,6]],
+ wizard: [[16,18,17,20,19],[14,11,13,15,12],[13,9,11,13,10],[11,7,9,11,8],[10,5,7,9,6],[8,3,5,7,4]],
+ priest: [[16,18,17,20,19],[10,14,13,16,15],[9,13,12,15,14],[7,11,10,13,12],[6,10,9,12,11],[5,9,8,11,10],[4,8,7,10,9],[2,6,5,8,7]],
+ rogue: [[16,18,17,20,19],[13,14,12,16,15],[12,12,11,15,13],[11,10,10,14,11],[10,8,9,13,9],[9,6,8,12,7],[8,4,7,11,5]],
+ psion: [[16,18,17,20,19],[13,15,10,16,15],[12,13,9,15,14],[11,11,8,13,12],[10,9,7,12,7],[9,7,6,11,9],[8,5,5,9,7]],
+ creature: [[16,18,17,20,19],[14,16,15,17,17],[13,15,14,16,16],[11,13,12,13,14],[10,12,11,12,13],[8,10,9,9,11],[7,9,8,8,10],[5,7,6,5,8],[4,6,5,4,7],[3,5,4,4,6]],
+ };
+ var classSaveMods = {
+ undefined: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ paladin: {att:'con',par:2,poi:2,dea:2,rod:2,sta:2,wan:2,pet:2,pol:2,bre:2,spe:2,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ };
+ var raceSaveMods = {
+ undefined: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ dwarf: {att:'con',par:0,poi:3.5,dea:0,rod:3.5,sta:3.5,wan:3.5,pet:0,pol:0,bre:0,spe:3.5,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ elf: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ gnome: {att:'con',par:0,poi:0,dea:0,rod:3.5,sta:3.5,wan:3.5,pet:0,pol:0,bre:0,spe:3.5,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ halfelf: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ halfling: {att:'con',par:0,poi:3.5,dea:0,rod:3.5,sta:3.5,wan:3.5,pet:0,pol:0,bre:0,spe:3.5,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ halforc: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ human: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ creature: {att:'con',par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ };
+ var saveFormat = Object.freeze({
+ Paralysis: {save:fields.Saves_paralysis,mod:fields.Saves_modParalysis,mon:fields.Saves_monParalysis,index:0},
+ Poison: {save:fields.Saves_poison,mod:fields.Saves_modPoison,mon:fields.Saves_monPoison,index:0},
+ Death: {save:fields.Saves_death,mod:fields.Saves_modDeath,mon:fields.Saves_monDeath,index:0},
+ Rod: {save:fields.Saves_rod,mod:fields.Saves_modRod,mon:fields.Saves_monRod,index:1},
+ Staff: {save:fields.Saves_staff,mod:fields.Saves_modStaff,mon:fields.Saves_monStaff,index:1},
+ Wand: {save:fields.Saves_wand,mod:fields.Saves_modWand,mon:fields.Saves_monWand,index:1},
+ Petrification: {save:fields.Saves_petrification,mod:fields.Saves_modPetrification,mon:fields.Saves_monPetrification,index:2},
+ Polymorph: {save:fields.Saves_polymorph,mod:fields.Saves_modPolymorph,mon:fields.Saves_monPolymorph,index:2},
+ Breath: {save:fields.Saves_breath,mod:fields.Saves_modBreath,mon:fields.Saves_monBreath,index:3},
+ Spell: {save:fields.Saves_spell,mod:fields.Saves_modSpell,mon:fields.Saves_monSpell,index:4},
+ });
+ var saveAttributes = Object.freeze({
+ Strength: {save:fields.Strength,mod:fields.Saves_modStrength},
+ Constitution: {save:fields.Constitution,mod:fields.Saves_modConstitution},
+ Dexterity: {save:fields.Dexterity,mod:fields.Saves_modDexterity},
+ Intelligence: {save:fields.Intelligence,mod:fields.Saves_modIntelligence},
+ Wisdom: {save:fields.Wisdom,mod:fields.Saves_modWisdom},
+ Charisma: {save:fields.Charisma,mod:fields.Saves_modCharisma},
+ });
+ var classNonProfPenalty = {};
+ var raceToHitMods = {
+ elf: [['bow',1],['longsword',1],['shortsword',1]],
+ halfling: [['sling',1],['thrownblade',1]],
+ };
+ var classAllowedWeaps = {
+ warrior: ['any'],
+ fighter: ['any'],
+ ranger: ['any'],
+ paladin: ['any'],
+ beastmaster: ['any'],
+ barbarian: ['any'],
+ defender: ['axe','clubs','flails','longblade','fencingblade','mediumblade','shortblade','polearm'],
+ wizard: ['dagger','staff','dart','knife','sling'],
+ mage: ['dagger','staff','dart','knife','sling'],
+ mu: ['dagger','staff','dart','knife','sling'],
+ abjurer: ['dagger','staff','dart','knife','sling'],
+ conjurer: ['dagger','staff','dart','knife','sling'],
+ diviner: ['dagger','staff','dart','knife','sling'],
+ enchanter: ['dagger','staff','dart','knife','sling'],
+ illusionist: ['dagger','staff','dart','knife','sling'],
+ invoker: ['dagger','staff','dart','knife','sling'],
+ necromancer: ['dagger','staff','dart','knife','sling'],
+ transmuter: ['dagger','staff','dart','knife','sling'],
+ priest: ['clubs','hammer','staff'],
+ cleric: ['clubs','hammer','staff'],
+ druid: ['club','sickle','dart','spear','dagger','scimitar','sling','staff'],
+ healer: ['club','quarterstaff','mancatcher','sling'],
+ priestofagriculture: ['hooks','flails','handaxe','throwingaxe','scythe','sickle'],
+ priestofancestors: ['club','dagger','dirk','dart','knife','staff'],
+ priestofanimals: ['hooks','cestus','clubs','maingauche','greatblade','longblade','mediumblade','shortblade','fencingblade','warhammer'],
+ priestofarts: ['bow'],
+ priestoflife: ['club','quarterstaff','mancatcher','sling'],
+ priestofwar: ['any'],
+ priestoflight: ['dart','javelin','spears'],
+ priestofknowledge: ['sling','quarterstaff'],
+ shaman: ['longblade','mediumblade','shortblade','blowgun','club','staff','shortbow','horsebow','handcrossbow'],
+ rogue: ['club','shortblade','dart','handcrossbow','lasso','shortbow','sling','broadsword','longsword','staff'],
+ thief: ['club','shortblade','dart','handcrossbow','lasso','shortbow','sling','broadsword','longsword','staff'],
+ bard: ['any'],
+ assassin: ['any'],
+ psion: ['shortbow','handcrossbow','lightcrossbow','shortblade','clubs','axe','horsemanspick','scimitar','spears','warhammer'],
+ };
+ var classAllowedArmour = {
+ warrior: ['any'],
+ fighter: ['any'],
+ ranger: ['any'],
+ paladin: ['any'],
+ beastmaster: ['any'],
+ barbarian: ['padded','leather','hide','brigandine','ringmail','scalemail','chainmail','shield','ring','magicitem','cloak'],
+ defender: ['any'],
+ wizard: ['magicitem','ring','cloak'],
+ mage: ['magicitem','ring','cloak'],
+ mu: ['magicitem','ring','cloak'],
+ abjurer: ['magicitem','ring','cloak'],
+ conjurer: ['magicitem','ring','cloak'],
+ diviner: ['magicitem','ring','cloak'],
+ enchanter: ['magicitem','ring','cloak'],
+ illusionist: ['magicitem','ring','cloak'],
+ invoker: ['magicitem','ring','cloak'],
+ necromancer: ['magicitem','ring','cloak'],
+ transmuter: ['magicitem','ring','cloak'],
+ priest: ['any'],
+ cleric: ['any'],
+ druid: ['leather','padded','hide','woodenshield','magicitem','ring','cloak'],
+ healer: ['any'],
+ priestofagriculture: ['leather','padded','hide','woodenshield','magicitem','ring','cloak'],
+ priestofancestors: ['magicitem','ring','cloak'],
+ priestofanimals: ['leather','padded','hide','magicitem','ring','cloak'],
+ priestofarts: ['magicitem','ring','cloak'],
+ priestofbirth: ['magicitem','ring','cloak'],
+ priestofchildren: ['magicitem','ring','cloak'],
+ priestofcommunity: ['any'],
+ priestofcompetition: ['any'],
+ priestofcrafts: ['leather','padded','hide','shields','magicitem','ring','cloak'],
+ priestofculture: ['any','-shields'],
+ priestofdarkness: ['leather','padded','hide','magicitem','ring','cloak'],
+ priestofnight: ['leather','padded','hide','magicitem','ring','cloak'],
+ priestoflife: ['any'],
+ priestofwar: ['any'],
+ priestoflight: ['studdedleather','ringmail','chainmail','shield','ring','magicitem','cloak'],
+ priestofknowledge: ['magicitem','ring','cloak'],
+ shaman: ['padded','leather','hide','brigandine','ringmail','scalemail','chainmail','splintmail','bandedmail','shield','ring','magicitem','cloak'],
+ rogue: ['padded','leather','studdedleather','elvenchain','shield','ring','magicitem','cloak'],
+ thief: ['padded','leather','studdedleather','elvenchain','shield','ring','magicitem','cloak'],
+ bard: ['padded','leather','hide','brigandine','ringmail','scalemail','chainmail','ring','magicitem','cloak'],
+ assassin: ['any'],
+ psion: ['leather','studdedleather','hide','smallshield','ring','magicitem','cloak'],
+ };
+ var weapMultiAttks = {
+ fighter: {
+ Levels: ['0','7','13'],
+ Proficient: { melee: ['0','1/2','1'],
+ ranged: ['0','0','0'],
+ },
+ },
+ All: {
+ Specialist: { melee: ['1/2','1','3/2'],
+ lightxbow: ['0','1/2','1'],
+ heavyxbow: ['0','1/2','1'],
+ throwndagger: ['1','2','3'],
+ throwndart: ['1','2','3'],
+ bow: ['0','0','0'],
+ arquebus: ['1/3','2/3','7/6'],
+ blowgun: ['1','2','3'],
+ knife: ['1','2','3'],
+ sling: ['1','2','3'],
+ ranged: ['0','1/2','1'],
+ },
+ },
+ };
+
+ const punchWrestle = [ {punch:'Haymaker',dmg:2,ko:25,wrestle:'Bearhug',hold:true},
+ {punch:'Wild swing',dmg:0,ko:2,wrestle:'Leg twist',hold:false},
+ {punch:'Uppercut',dmg:2,ko:15,wrestle:'Headlock',hold:true},
+ {punch:'Hook',dmg:2,ko:12,wrestle:'Gouge',hold:false},
+ {punch:'Rabbit punch',dmg:2,ko:5,wrestle:'Arm lock',hold:true},
+ {punch:'Glancing blow',dmg:1,ko:3,wrestle:'Kick',hold:false},
+ {punch:'Jab',dmg:2,ko:8,wrestle:'Gouge',hold:false},
+ {punch:'Combination',dmg:2,ko:10,wrestle:'Throw',hold:false},
+ {punch:'Uppercut',dmg:1,ko:9,wrestle:'Headlock',hold:true},
+ {punch:'Combination',dmg:1,ko:10,wrestle:'Leg lock',hold:true},
+ {punch:'Glancing blow',dmg:1,ko:3,wrestle:'Elbow smash',hold:false},
+ {punch:'Hook',dmg:2,ko:10,wrestle:'Gouge',hold:false},
+ {punch:'Kidney punch',dmg:1,ko:5,wrestle:'Throw',hold:false},
+ {punch:'Hook',dmg:2,ko:9,wrestle:'Leg lock',hold:false},
+ {punch:'Uppercut',dmg:1,ko:8,wrestle:'Leg twist',hold:false},
+ {punch:'Jab',dmg:2,ko:6,wrestle:'Arm lock',hold:true},
+ {punch:'Glancing blow',dmg:1,ko:2,wrestle:'Elbow smash',hold:false},
+ {punch:'Kidney punch',dmg:1,ko:5,wrestle:'Trip',hold:false},
+ {punch:'Rabbit punch',dmg:1,ko:3,wrestle:'Kick',hold:false},
+ {punch:'Wild swing',dmg:0,ko:1,wrestle:'Arm twist',hold:false},
+ {punch:'Haymaker',dmg:2,ko:10,wrestle:'Bearhug',hold:true}
+ ];
+
+ const reIgnore = /[-_\s\(\)]/g;
+ const settings_icon = 'https://s3.amazonaws.com/files.d20.io/images/11920672/7a2wOvU1xjO-gK5kq5whgQ/thumb.png?1440940765';
+ const defaultImg = 'https://s3.amazonaws.com/files.d20.io/images/2796029/tJUjL-ilXyG-Ohu6T2Ykvg/thumb.png?1390103367';
+ const defaultAs = 'RPGMaster';
+ const archive = false;
+ const use3Ddice = true;
+ const stdDB = ['mu_spells_db','pr_spells_db','powers_db','mi_db','mi_db_ammo','mi_db_armour','mi_db_light','mi_db_potions','mi_db_rings','mi_db_scrolls_books','mi_db_wands_staves_rods','mi_db_weapons','attacks_db','class_db','race_db','race_db_creatures','styles_db'];
+
+ const reCastMIspellCmd = /!magic\s+--cast-spell\s+MI\s*\|/im;
+ const reCastMIpowerCmd = /!magic\s+--cast-spell\s+MI-POWERS?\s*\|/im;
+ const reSpecs = /}}\s*Specs=\s*?(\[[^{]*?\])\s*?{{/im;
+ const reSpecsAll = /\[\s*?(\w[-\+\s\w\|]*?)\s*?,\s*?(\w[-\s\w\|]*?\w)\s*?,\s*?(\w[\s\w\|]*?\w)\s*?,\s*?(\w[-\+\s\w\|]*?\w)\s*?\]/g;
+ const reData = /}}\s*?\w*?data\s*?=(.*?){{/im;
+ const reDataAll = /\[.+?\]/g;
+ const reSpecClass = /\[\s*?\w[\s\|\w\-\+]*?\s*?,\s*?(\w[\s\|\w\-]*?)\s*?,.*?\]/g;
+ const reSpecSuperType = /}}\s*Specs=\s*?\[\s*?\w[\s\|\w\-\+]*?\s*?,\s*?\w[\s\|\w\-]*?\w\s*?,\s*?\d+H(?:\|\d*H)\s*?,\s*?(\w[\s\|\w\-]*?\w)\s*?\]/im;
+ const reDataSpeed = /}}\s*?\w*?data\s*?=.*?[\[,]\s*?sp:([d\d\+\-\*\/.]+?)[,\s\]]/im;
+ const reDataCharge = /}}\s*?\w*?data\s*?=.*?[\[,]\s*?rc:([\w\+\-]+?)[,\s\]]/im;
+ const reDataCost = /}}\s*?\w*?data\s*?=.*?[\[,]\s*?gp:(\d+?\.?\d*?)[,\s\]]/im;
+ const reDataLevel = /}}\s*?\w*?data\s*?=.*?[\[,]\s*?lv:(\d+?)[,\s\]]/im;
+ const reLevel = /[\[,]\s*?lv:(\d+?)[,\s\]]/im;
+ const reClassData = /}}\s*?ClassData\s*?=(.*?){{/im;
+ const reSpellData = /}}\s*?SpellData\s*?=(.*?){{/im;
+ const reRepeatingTable = /^(repeating_.*)_\$(\d+)_.*$/;
+ const reNotWeaponData = /}}[\s\w\-]*?(?"],
+ [/\\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, "&"],
+ ];
+
+ const dbEncoders = [
+ [/\\/gm,"\\\\"],
+ [/\r?\n/gm,'\\n'],
+ [/'/gm,"\\'"],
+ [/&/gm,"\\\\amp"],
+ [/>/gm,"\\\\gt"],
+ [/"],
+ [/\\lt/gm, "<"],
+ ];
+
+ const pallet = Object.freeze({
+ fancy: {
+ def: {outer:'yellow',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'transparent',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'5% 5% 2px 5%',bodypad:'4px 5% 10% 10%',bodybox:'',rowbox:'purple',rowdark:'transparent',rowdarktext:'black',rowlight:'transparent',rowlighttext:'black',rowpad:'4px',outerimg:'https://s3.amazonaws.com/files.d20.io/images/279722596/LxsTe-cbwk5j9L0ipM3GLw/thumb.jpg?1649510600',titleimg:'https://s3.amazonaws.com/files.d20.io/images/279800986/SqFez5dbn2roAsokDaBAPw/thumb.jpg?1649536002',bodyimg:'https://s3.amazonaws.com/files.d20.io/images/279800959/KyHThjxjXeZQ-b_uC6yCjQ/thumb.jpg?1649535995'},
+ spell: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'transparent',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'20% 10% 2px 10%',bodypad:'4px 12% 5% 12%',bodybox:'',rowbox:'purple',rowdark:'transparent',rowdarktext:'black',rowlight:'transparent',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'https://s3.amazonaws.com/files.d20.io/images/279801150/vQ_1KKR72-7DTAusJzkt0w/thumb.png?1649536043',bodyimg:'https://s3.amazonaws.com/files.d20.io/images/279801125/opM7Y6m20DGLPeP-hrXpCA/thumb.png?1649536037'},
+ potion: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'transparent',titletext:'black; text-shadow: 1px 1px 1px gray',titlepad:'60% 10% 2px 10%',bodypad:'10% 5% 15% 8%',bodybox:'',rowbox:'mediumturquoise',rowdark:'transparent',rowdarktext:'white',rowlight:'transparent',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'https://s3.amazonaws.com/files.d20.io/images/279798022/Qgs1fGmOup8_9mtzoEeSxw/thumb.png?1649535031',bodyimg:'https://s3.amazonaws.com/files.d20.io/images/279798050/hQ4nWnVGPDINtjidt8-1eg/thumb.png?1649535040'},
+ weapon: {outer:'yellow',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'transparent',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'5% 5% 2px 5%',bodypad:'4px 5% 10% 10%',bodybox:'',rowbox:'purple',rowdark:'transparent',rowdarktext:'black; text-shadow: 1px 1px 1px white',rowlight:'transparent',rowlighttext:'black; text-shadow: 1px 1px 1px white',rowpad:'4px',outerimg:'https://s3.amazonaws.com/files.d20.io/images/279722596/LxsTe-cbwk5j9L0ipM3GLw/thumb.jpg?1649510600',titleimg:'',bodyimg:'https://s3.amazonaws.com/files.d20.io/images/257648113/iUlG62xcBc6AdUj5lv32Ww/max.png?1638047575'},
+ attack: {outer:'purple',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'4px solid maroon',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'4px 4px 1px 4px',bodypad:'0px',bodybox:'4px solid gray',rowbox:'none',rowdark:'white',rowdarktext:'black',rowlight:'white',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',dmgslabel:'S/M',dmgllabel:'L'},
+ menu: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'blue',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'teal',rowdark:'lightblue',rowdarktext:'black',rowlight:'lightcyan',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:''},
+ message: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'white',titletext:'black',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'1px solid black',rowbox:'',rowdark:'white',rowdarktext:'black',rowlight:'white',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:''},
+ warning: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'crimson',titletext:'white',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'pink',rowdarktext:'black',rowlight:'mistyrose',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ },
+ plain: {
+ def: {outer:'blue',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'blue',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'lightblue',rowdarktext:'black',rowlight:'lightcyan',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ spell: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'firebrick',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'pink',rowdarktext:'black',rowlight:'mistyrose',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ potion: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'forestgreen',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'mediumturquoise',rowdark:'khaki',rowdarktext:'black',rowlight:'lightgoldenrodyellow',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ weapon: {outer:'yellow',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'gray',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'gainsboro',rowdarktext:'black; text-shadow: 1px 1px 1px white',rowlight:'ghostwhite',rowlighttext:'black; text-shadow: 1px 1px 1px white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ attack: {outer:'purple',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'4px solid maroon',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'4px 4px 1px 4px',bodypad:'0px',bodybox:'4px solid gray',rowbox:'none',rowdark:'white',rowdarktext:'black',rowlight:'white',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',dmgslabel:'S/M',dmgllabel:'L'},
+ menu: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'blue',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'teal',rowdark:'lightblue',rowdarktext:'black',rowlight:'lightcyan',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ message: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'white',titletext:'black',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'1px solid black',rowbox:'',rowdark:'white',rowdarktext:'black',rowlight:'white',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:''},
+ warning: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'crimson',titletext:'white',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'pink',rowdarktext:'black',rowlight:'mistyrose',rowlighttext:'black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ },
+ dark: {
+ def: {outer:'darkgoldenrod',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'blue',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'navy',rowdarktext:'white',rowlight:'blueviolet',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ spell: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'firebrick',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'darkmagenta',rowdarktext:'white',rowlight:'darkorchid',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ potion: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'forestgreen',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'mediumturquoise',rowdark:'darkgoldenrod',rowdarktext:'white; text-shadow: 1px 1px 1px black',rowlight:'goldenrod',rowlighttext:'white; text-shadow: 1px 1px 1px black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ weapon: {outer:'darkgoldenrod',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'gray',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'dimgray',rowdarktext:'white; text-shadow: 1px 1px 1px black',rowlight:'darkgray',rowlighttext:'white; text-shadow: 1px 1px 1px black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ attack: {outer:'purple',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'4px solid maroon',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'4px 4px 1px 4px',bodypad:'0px',bodybox:'4px solid gray',rowbox:'none',rowdark:'dimgray',rowdarktext:'white; text-shadow: 1px 1px 1px black',rowlight:'dimgray',rowlighttext:'white; text-shadow: 1px 1px 1px black',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',dmgslabel:'S/M',dmgllabel:'L'},
+ menu: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'blue',titletext:'white; text-shadow: 1px 1px 1px gray',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'teal',rowdark:'navy',rowdarktext:'white',rowlight:'blueviolet',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ message: {outer:'white',outerpad:'',shadow:'rgba(0,0,0,0) 0px 0px',titlebox:'black',titletext:'white',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'1px solid white',rowbox:'',rowdark:'black',rowdarktext:'white',rowlight:'black',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:''},
+ warning: {outer:'black',outerpad:'',shadow:'rgba(0,0,0,0.4) 3px 3px',titlebox:'crimson',titletext:'white',titlepad:'1px 1px 1px 1px',bodypad:'4px 4px 4px 4px',bodybox:'',rowbox:'purple',rowdark:'darkmagenta',rowdarktext:'white',rowlight:'darkorchid',rowlighttext:'white',rowpad:'4px',outerimg:'',titleimg:'',bodyimg:'',rowimg:''},
+ }
+ });
+
+ const acImg = 'https://s3.amazonaws.com/files.d20.io/images/280889787/N6NbbkLDe92C4e5DDtmkaw/thumb.png?1650135426';
+ const dmgImg = 'https://s3.amazonaws.com/files.d20.io/images/280890292/ZBDEOKwQHCPeY2yQJuhkeA/thumb.png?1650135612';
+ const hpImg = 'https://s3.amazonaws.com/files.d20.io/images/281063429/1ySUC06qy_MuhY-_Be_pVQ/thumb.png?1650223020';
+ const slashImg = 'https://s3.amazonaws.com/files.d20.io/images/281331848/XnspIFctdnld8LVG3_m5RQ/thumb.png?1650393752';
+ const pierceImg = 'https://s3.amazonaws.com/files.d20.io/images/281331832/DYgW_xqlORNJ77oigkFqAA/thumb.png?1650393745';
+ const bludgeonImg = 'https://s3.amazonaws.com/files.d20.io/images/281331818/rSZVRXYkRNR4K9Ru6CXbVw/thumb.png?1650393737';
+ const sacImg = 'https://s3.amazonaws.com/files.d20.io/images/281054605/oNYktYKEmF9_ngePXyUcPw/thumb.png?1650219538';
+ const pacImg = 'https://s3.amazonaws.com/files.d20.io/images/281054578/FeeVqF8X-rgeEP6fg4CWKg/thumb.png?1650219526';
+ const bacImg = 'https://s3.amazonaws.com/files.d20.io/images/281054552/-i1SuQ4Rx1OO7cXPtlggNg/thumb.png?1650219515';
+ const heart = ['https://s3.amazonaws.com/files.d20.io/images/281063429/1ySUC06qy_MuhY-_Be_pVQ/thumb.png?1650223020',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334582/74iFWTTF47pFyvmGd1WWnw/thumb.png?1650395033',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334596/8yhpUHhYL7bQIlLZfHGqjw/thumb.png?1650395041',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334612/FpyTBj_oaJS6_GaZmlsfvA/thumb.png?1650395047',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334628/-4nbQ36qch58EK0BWgytRA/thumb.png?1650395055',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334655/OH7HS1U-xYFUTJjIAypqFQ/thumb.png?1650395061',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334666/CByDv4kCKWcaV9LabxwV-A/thumb.png?1650395067',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334682/xbcpGhbmeEAf3ZmKEgs3Ow/thumb.png?1650395074',
+ 'https://s3.amazonaws.com/files.d20.io/images/281334693/xTlsD3NHddK4g3-nlQVCDg/thumb.png?1650395080'
+ ];
+/* var handoutIDs = {
+ AttackMasterHelp: '',
+ AttacksDatabaseHelp: '',
+ ClassDatabaseHelp: '',
+ CommandMasterHelp: '',
+ EffectsDatabaseHelp: '',
+ InitiativeMasterHelp: '',
+ MagicDatabaseHelp: '',
+ MagicMasterHelp: '',
+ RPGMasterCharSheetSetup: '',
+ RoundMasterHelp: '',
+ RPGMasterTemplatesHelp: '',
+ WeaponArmourDatabaseHelp: '',
+ };
+*/ var DBindex;
+ var magicList = {};
+ var RPGMap = {};
+ var apis = {magic:false,attk:false,init:false};
+ var lastMsg = [];
+ var doneRNmsg = false;
+
+ const isString = (s) => 'string' === typeof s || s instanceof String;
+ const isArray = (a) => Array.isArray(a);
+ const flatten = (a) => isArray(a) ? a.reduce((m,e)=>[...m, ...flatten(e)],[]) : [a];
+
+ /**
+ * In the inline roll evaluator from ChatSetAttr script v1.9
+ * by Joe Singhaus and C Levett.
+ **/
+
+ var processInlinerolls = function (msg) {
+ if (msg.inlinerolls && msg.inlinerolls.length) {
+ return msg.inlinerolls.map(v => {
+ const ti = v.results.rolls.filter(v2 => v2.table)
+ .map(v2 => v2.results.map(v3 => v3.tableItem.name).join(", "))
+ .join(", ");
+ return (ti.length && ti) || v.results.total || 0;
+ })
+ .reduce((m, v, k) => m.replace(new RegExp('\\$\\[\\['+k+'\\]\\]','img'),'[['+v+'['+msg.inlinerolls[k].expression+'] ]]'), msg.content);
+ } else {
+ return msg.content;
+ }
+ };
+
+ /*
+ * Check the version of a Character Sheet database against
+ * the current version in the API. Delete old versions so
+ * API versions are used and indexed.
+ */
+
+ var del_Old_DBs = function() {
+
+ var update = false;
+
+ _.each( dbNames, (db,dbName) => {
+ let dbFullName = dbName.replace(/_/g,'-'),
+ dbCS = findObjs({ type:'character', name:dbFullName },{caseInsensitive:true}),
+ dbVersion = 0.0,
+ msg, versionObj;
+
+ if (!dbCS || !dbCS.length) return;
+
+ dbCS = dbCS[0];
+
+ if (_.isUndefined(LibFunctions.attrLookup( dbCS, fields.dbVersion ))) {
+ setTimeout( () => del_Old_DBs(), 5000 );
+ return;
+
+ } else {
+
+ dbVersion = parseFloat(LibFunctions.attrLookup( dbCS, fields.dbVersion )) || dbVersion;
+
+ if (dbVersion >= (parseFloat(db.version) || 0)) return;
+
+ log('Deleting '+dbFullName+' v'+dbVersion);
+ dbCS.remove();
+ update = true;
+ }
+ });
+ if (update) LibFunctions.updateDBindex();
+ return;
+ }
+
+ /*
+ * Function to generate unique IDs for creating objects in Roll20
+ */
+
+ const generateUUID = function () {
+ var a = 0,
+ b = [];
+ return function () {
+ var c = (new Date()).getTime() + 0,
+ d = c === a;
+ a = c;
+ for (var e = new Array(8), f = 7; 0 <= f; f--) {
+ e[f] = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(c % 64);
+ c = Math.floor(c / 64);
+ }
+ c = e.join("");
+ if (d) {
+ for (f = 11; 0 <= f && 63 === b[f]; f--) {
+ b[f] = 0;
+ }
+ b[f]++;
+ } else {
+ for (f = 0; 12 > f; f++) {
+ b[f] = Math.floor(64 * Math.random());
+ }
+ }
+ for (f = 0; 12 > f; f++) {
+ c += "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(b[f]);
+ }
+ return c;
+ };
+ }();
+ const generateRowID = function () {
+ return generateUUID().replace(/_/g, "Z");
+ };
+
+ /**
+ * Find the GM, generally when a player can't be found
+ */
+
+ var findTheGM = function() {
+ var playerGM,
+ players = findObjs({ _type:'player' });
+
+ if (players.length !== 0) {
+ if (!_.isUndefined(playerGM = _.find(players, function(p) {
+ var player = p;
+ if (player) {
+ if (playerIsGM(player.id)) {
+ return player.id;
+ }
+ }
+ }))) {
+ return playerGM.id;
+ }
+ }
+ return undefined;
+ }
+
+ /*
+ * Display a message with a link to the Release Notes
+ */
+
+ var displayReleaseNotesLink = function() {
+ var handoutIDs = LibFunctions.getHandoutIDs();
+ if (!doneRNmsg) {
+ doneRNmsg = true;
+ LibFunctions.sendFeedback('
You can read the latest **[Release Notes here]('+fields.journalURL+handoutIDs.RPGMReleaseNotes+')**
');
+ }
+ }
+
+ String.prototype.dbName = function() {
+ return this.toLowerCase().replace(reIgnore,'');
+ }
+
+ String.prototype.dispName = function() {
+ return (this || '').replace(/\-/g,' ');
+ }
+
+ String.prototype.hyphened = function() {
+ return (this || '').replace(/\s/g,'-');
+ }
+
+ String.prototype.trueCompare = function(txt) {
+ return (this || '').dbName() === (toString(txt) || '').dbName();
+ }
+
+ class AbilityObj {
+ constructor( dBname, abilityObj, ctObj, source ) {
+ this.dB = dBname;
+ this.obj = abilityObj;
+ this.ct = ctObj;
+ this.source = source;
+ this.api = (abilityObj && abilityObj[1]) ? (abilityObj[1].body.trim()[0] == '!') : false;
+ }
+
+ specs(re = reSpecs) {
+ let specStr = this.obj[1].body.match(re);
+ return specStr ? [...('['+specStr[0]+']').matchAll(reSpecsAll)] : undefined;
+ }
+ data(re = reData) {
+ let specStr = this.obj[1].body.match(re);
+ return specStr ? [...('['+specStr[0]+']').matchAll(reDataAll)] : undefined;
+ }
+ hands(re = reSpecs) {
+ let specStr = this.obj[1].body.match(re);
+ return specStr ? [...('['+specStr[0]+']').matchAll(reHands)].concat([...('['+specStr[0]+']').matchAll(reHands2)] || []) : undefined;
+ }
+ }
+
+ class CharTable {
+ constructor( property, attrs, defaultVal ) {
+ if (!property || !isArray(property) || property.length < 2) throw {name:'libRPGMaster Error',message:'Invalid attribute definition in table constructor'};
+ this.property = property;
+ this.attrs = attrs || {};
+ this.defaultVal = defaultVal || {current:'',max:''};
+ }
+ }
+
+ class CharTableArray {
+ constructor( character, table, col ) {
+ if (!character) throw {name:'libRPGMaster Error',message:'Invalid character object in table constructor'};
+ if (!table || !isArray(table) || table.length < 2) throw {name:'libRPGMaster Error',message:'Invalid table definition in table constructor'};
+ this.character = character;
+ this.table = table;
+ this.tableType;
+ this.fieldGroup;
+ this.values;
+ this.sortKeys;
+ this.col = (_.isUndefined(col) || _.isNull(col) || (table && !_.isNull(table) && !table[1] && col && col==1)) ? '' : col;
+ }
+
+ /*
+ * A method to get the whole of a repeating table in
+ * two parts: an array of objects indexed by Roll20 object IDs,
+ * and an array of object IDs indexed by repeating table row number.
+ * Returns an object containing the table, and all parameters defining
+ * that table and where it came from.
+ */
+
+ addTable(attrDef,defaultVal,caseSensitive) {
+ if (_.isUndefined(attrDef) || !isArray(attrDef) || attrDef.length < 2) throw {name:'libRPGMaster Error',message:'No table attribute supplied for '+this.table[0]};
+ let rowName, name = attrDef[0];
+ if (this.table && !_.isNull(this.table)) {
+ rowName = this.table[0]+this.col+'_$0_'+attrDef[0]+this.col;
+ } else {
+ rowName = name;
+ }
+
+ if (_.isUndefined(defaultVal)) {
+ defaultVal=attrDef[2];
+ }
+
+ if (!this.hasOwnProperty(name)) {
+ this[name] = new CharTable( attrDef );
+ }
+ this[name].defaultVal[attrDef[1]] = defaultVal;
+ let match=rowName.match(/^(repeating_.*)_\$(\d+)_.*$/);
+ if(match){
+ let createOrderKeys=[],
+ attrMatcher=new RegExp(`^${rowName.replace(/_\$\d+_/,'_([-\\da-zA-Z]+)_')}$`,(caseSensitive?'i':'')),
+ attrs=_.chain(findObjs({type:'attribute', characterid:this.character.id}))
+ .map((a)=>{
+ return {attr:a,match:a.get('name').match(attrMatcher)};
+ })
+ .filter((o)=>o.match)
+ .each((o)=>createOrderKeys.push(o.match[1]))
+ .reduce((m,o)=>{ m[o.match[1]]=o.attr; return m;},{})
+ .value(),
+ sortOrderKeys = _.chain( ((findObjs({
+ type:'attribute',
+ characterid:this.character.id,
+ name: `_reporder_${match[1]}`
+ })[0]||{get:_.noop}).get('current') || '' ).split(/\s*,\s*/))
+ .intersection(createOrderKeys)
+ .union(createOrderKeys)
+ .value();
+
+ if (_.isUndefined(this.sortKeys)) {
+ this.sortKeys = sortOrderKeys;
+ } else {
+ this.sortKeys = (sortOrderKeys.length > this.sortKeys.length) ? sortOrderKeys.concat(_.difference(this.sortKeys,sortOrderKeys)) : this.sortKeys.concat(_.difference(sortOrderKeys,this.sortKeys));
+ }
+ this[name].attrs=attrs;
+ } else {
+ this[name].attrs=[];
+ if (_.isUndefined(this.sortKeys)) {
+ this.sortKeys = [];
+ }
+ }
+ return this;
+ }
+
+ /*
+ * Find all the necessary tables to manage a repeating
+ * section of a character sheet. Dynamically driven by
+ * the table field definitions in the 'fields' object.
+ */
+
+ addAllTables( fieldGroup, caseSensitive ) {
+
+ var rows = {};
+
+ this.fieldGroup = fieldGroup;
+ this.values = [new Set()];
+ _.each( fields, (elem,key) => {
+ if (key.startsWith(fieldGroup)
+ && ['current','max'].includes(String(elem[1]).toLowerCase())) {
+ rows[key]=elem;
+ if (_.isUndefined(this.values[elem[0]])) {
+ this.values[elem[0]] = {current:'',max:''};
+ }
+ this.values[elem[0]][elem[1]] = elem[2] || '';
+ };
+ });
+ _.each(rows, (elem,key) => {
+ this.addTable( elem, elem[2], caseSensitive );
+ });
+ return this;
+ }
+
+ /**
+ * A function to take a table obtained using getTableField() and a row number, and
+ * safely return the value of the table row, or undefined. Uses the table object
+ * parameters such as the character object it came from and the field property.
+ * If the row entry is undefined use a default value if set in the getTableField() call,
+ * which can be overridden with an optional parameter. Can just return the row
+ * object or can return a different property of the object using the second optional parameter.
+ */
+
+ tableLookup( attrDef, index, defVal, retObj ) {
+
+ if (!attrDef || !isArray(attrDef) || attrDef.length < 2) throw {name:'libRPGMaster Error',message:'No table attribute supplied for '+this.table[0]};
+ var val, name = attrDef[0];
+ if (_.isUndefined(retObj)) {
+ retObj=false;
+ } else if (retObj === true) {
+ defVal=false;
+ }
+ if (_.isUndefined(defVal)) {
+ defVal=true;
+ }
+ if (this[name]) {
+ let property = (retObj === true) ? null : ((retObj === false) ? attrDef : retObj);
+ defVal = (defVal===false) ? (undefined) : ((defVal===true) ? this[name].defaultVal[attrDef[1]] : defVal);
+ if (index>=0) {
+ let attrs = this[name].attrs,
+ sortOrderKeys = this.sortKeys;
+ if (index
{
+ if (_.isUndefined(elem.attrs)) return;
+ currentVal = (!values || _.isUndefined(values[key])) ? elem.defaultVal['current'] : values[key]['current'];
+ maxVal = (!values || _.isUndefined(values[key])) ? elem.defaultVal['max'] : values[key]['max'];
+ this.tableSet( [key,'current'], index, currentVal );
+ this.tableSet( [key,'max'], index, maxVal );
+ });
+ } else {
+ let rowObjID = generateRowID();
+ let namePt1 = this.table[0]+this.col+'_'+rowObjID+'_';
+ _.each( list, (elem,key) => {
+ if (_.isUndefined(elem.attrs)) return;
+ rowObj = createObj( "attribute", {characterid: this.character.id, name: (namePt1+key+this.col)} );
+ if (!values || _.isUndefined(values[key])) {
+ newVal = elem.defaultVal;
+ } else {
+ newVal = values[key];
+ }
+ rowObj.set(newVal);
+ this[key].attrs[rowObjID] = rowObj;
+ this.sortKeys[index] = rowObjID;
+ });
+ }
+ return this;
+ }
+
+ /*
+ * A function to find the index of a matching entry in a table
+ */
+
+ tableFind( attrDef, val ) {
+
+ val = val.dbName() || '-';
+ let property = attrDef[1];
+ if ((this.table[1] < 0) && val == (LibFunctions.attrLookup( this.character, attrDef ).dbName() || '-')) {
+ return -1;
+ }
+ let tableIndex = this.sortKeys.indexOf(
+ _.findKey(this[attrDef[0]].attrs, function( elem, objID ) {
+ return val == (elem.get(property).dbName() || '-');
+ })
+ );
+ return (tableIndex >= 0) ? tableIndex : undefined;
+ }
+
+ /*
+ * A function to set all rows of just one field of a table to
+ * a provided value, or its default if value not provided
+ */
+
+ tableDefault( attrDef, val ) {
+ if (!attrDef || !isArray(attrDef) || attrDef.length < 2) throw {name:'libRPGMaster Error',message:'No table attribute supplied for '+this.table[0]};
+ if (_.isUndefined(val) || _.isNull(val)) val = this[attrDef[0]].defaultVal[attrDef[1]];
+ if (!this[attrDef[0]]) throw {name:'libRPGMaster Error',message:'Invalid table attribute '+attrDef[0]+' supplied for '+this.table[0]};
+ _.each(this[attrDef[0]].attrs, obj => {
+ obj.set(attrDef[1],val);
+ });
+ return this;
+ }
+ }
+
+ class CSdbIndex {
+ constructor() {
+ this.mu_spells_db = {};
+ this.pr_spells_db = {};
+ this.powers_db = {};
+ this.mi_db = {};
+ this.race_db = {};
+ this.class_db = {};
+ this.attacks_db = {};
+ }
+ }
+
+
+ class LibFunctions {
+
+ static init(){
+
+ /** ------------------------------- Table Management ---------------------------- **/
+
+ /*
+ * A function to get the whole of a repeating table in
+ * two parts: an array of objects indexed by Roll20 object IDs,
+ * and an array of object IDs indexed by repeating table row number.
+ * Returns an object containing the table, and all parameters defining
+ * that table and where it came from.
+ */
+
+ LibFunctions.getTableField = function(character,tableObj,tableDef,attrDef,col,defaultVal,caseSensitive) {
+ if (_.isUndefined(tableObj) || _.isUndefined(tableObj.table)) tableObj = new CharTableArray( character, tableDef, col );
+ tableObj.addTable( attrDef, defaultVal, caseSensitive );
+ return tableObj;
+ }
+
+ /*
+ * Find all the necessary tables to manage a repeating
+ * section of a character sheet. Dynamically driven by
+ * the table field definitions in the 'fields' object.
+ */
+
+ LibFunctions.getTable = function( character, fieldGroup, col, tableObj, caseSensitive ) {
+ let tableDef = fieldGroup.tableDef;
+ if (_.isUndefined(tableObj) || _.isUndefined(tableObj.table)) tableObj = new CharTableArray( character, tableDef, col );
+ tableObj.addAllTables( fieldGroup.prefix, caseSensitive );
+ return tableObj;
+ }
+ /*
+ * Get all tables in a particular numbered group of tables,
+ * based not on columns but on a numbered sequence of prefixes
+ */
+
+ LibFunctions.getLvlTable = function( character, fieldGroup, lvl, tableObj, caseSensitive ) {
+ if (_.isUndefined(lvl) || _.isNull(lvl)) lvl = '';
+ let tableDef = [fieldGroup.tableDef[0]+lvl,fieldGroup.tableDef[1]];
+ if (_.isUndefined(tableObj) || _.isUndefined(tableObj.table)) tableObj = new CharTableArray( character, tableDef, null );
+ tableObj.addAllTables( fieldGroup.prefix, caseSensitive );
+ return tableObj;
+ }
+
+ /*
+ * Function to initialise a values[] array to hold data for
+ * setting a table row to.
+ */
+
+ LibFunctions.initValues = function( fieldGroup ) {
+
+ let values = [new Set()];
+ let rows = _.filter( fields, (elem,f) => {return f.startsWith(fieldGroup)})
+ .map(elem => {
+ if (_.isUndefined(values[elem[0]])) {
+ values[elem[0]] = {current:'',max:''};
+ }
+ values[elem[0]][elem[1]] = elem[2] || '';
+ });
+ return values;
+ }
+
+ /** ------------------------ Attribute Management ------------------------------ **/
+
+ /**
+ * A function to return the handle for the 'fields' object for the represented
+ * character sheet mapping, and an object of handles for other game-specific values.
+ **/
+
+ LibFunctions.getRPGMap = function() {
+ RPGMap.dbNames = dbNames;
+ RPGMap.fieldGroups = fieldGroups;
+ RPGMap.miTypeLists = miTypeLists;
+ RPGMap.clTypeLists = clTypeLists;
+ RPGMap.spTypeLists = spTypeLists;
+ RPGMap.baseThac0table = baseThac0table;
+ RPGMap.spellsPerLevel = spellsPerLevel;
+ RPGMap.spellLevels = spellLevels;
+ RPGMap.specMU = specMU;
+ RPGMap.ordMU = ordMU;
+ RPGMap.wisdomSpells = wisdomSpells;
+ RPGMap.casterLevels = casterLevels;
+ RPGMap.primeClasses = primeClasses;
+ RPGMap.classLevels = classLevels;
+ RPGMap.rangedWeapMods = rangedWeapMods;
+ RPGMap.saveLevels = saveLevels;
+ RPGMap.baseSaves = baseSaves;
+ RPGMap.classSaveMods = classSaveMods;
+ RPGMap.raceSaveMods = raceSaveMods;
+ RPGMap.defaultNonProfPenalty = defaultNonProfPenalty;
+ RPGMap.classNonProfPenalty = classNonProfPenalty;
+ RPGMap.raceToHitMods = raceToHitMods;
+ RPGMap.classAllowedWeaps = classAllowedWeaps;
+ RPGMap.classAllowedArmour = classAllowedArmour;
+ RPGMap.weapMultiAttks = weapMultiAttks;
+ RPGMap.punchWrestle = punchWrestle;
+ RPGMap.saveFormat = saveFormat;
+ RPGMap.saveAttributes = saveAttributes;
+// RPGMap.handoutIDs = handoutIDs;
+ RPGMap.reClassSpecs = reClassSpecs;
+ return [fields,RPGMap];
+ }
+
+ /**
+ * A function to lookup the value of any attribute, including repeating rows, without errors
+ * thus avoiding the issues with getAttrByName()
+ *
+ * Thanks to The Aaron for this, which I have modded to split and
+ * allow tables to be loaded once rather than multiple times.
+ */
+
+ LibFunctions.attrLookup = function(character,attrDef,tableDef,r,c='',caseSensitive=false, defVal=true) {
+ let name, match,
+ property = attrDef[1];
+
+ if (tableDef && isNaN(r)) return undefined;
+
+ if (tableDef && (tableDef[1] || r >= 0)) {
+ c = (tableDef[1] || c != 1) ? c : '';
+ name = tableDef[0] + c + '_$' + r + '_' + attrDef[0] + c;
+ } else {
+ name = attrDef[0];
+ }
+ defVal = (defVal === false ? undefined : (defVal === true ? attrDef[2] : defVal));
+ match=name.match(/^(repeating_.*)_\$(\d+)_.*$/);
+ if(match){
+ let index=match[2];
+ let tableObj = new CharTableArray( character, tableDef, c );
+ tableObj.addTable(attrDef,null,caseSensitive);
+ return tableObj.tableLookup(attrDef,index,false,!attrDef[1]);
+ } else {
+ let attrObj = findObjs({ type:'attribute', characterid:character.id, name:name}, {caseInsensitive: !caseSensitive});
+ if (!attrObj || attrObj.length == 0) {
+// log('attrLookup: no attribute found in '+character.get('name')+' with name:'+name+', property:'+property);
+ return (_.isUndefined(property) || _.isNull(property)) ? undefined : defVal;
+ } else if (_.isUndefined(property) || _.isNull(property)) {
+ return getObj('attribute',attrObj[0].id);
+ } else {
+ let value = getObj('attribute',attrObj[0].id).get(property);
+ return (_.isUndefined(value) ? defVal : value);
+ }
+ }
+ }
+
+ /**
+ * Check that an attribute exists, set it if it does, or
+ * create it if it doesn't using !setAttr
+ **/
+
+ LibFunctions.setAttr = function( character, attrDef, attrValue, tableDef, r, c, caseSensitive ) {
+
+ var name, attrObj, match;
+
+ if (_.isUndefined(attrDef)) {log('setAttr attrDef undefined:'+attrDef);return undefined;}
+ try {
+ name = attrDef[0];
+ } catch {
+ return undefined;
+ }
+
+ if (tableDef && (tableDef[1] || r >= 0)) {
+ c = (c && (tableDef[1] || c != 1)) ? c : '';
+ name = tableDef[0] + c + '_$' + r + '_' + attrDef[0] + c;
+ } else {
+ name = attrDef[0];
+ }
+ match=name.match(/^(repeating_.*)_\$(\d+)_.*$/);
+ if(match){
+ let tableObj = new CharTableArray( character, tableDef, c );
+ tableObj.addTable(attrDef,null,caseSensitive);
+ if (tableObj) {
+ attrObj = tableObj.tableLookup(attrDef,r,false,true);
+ }
+ } else {
+ attrObj = LibFunctions.attrLookup( character, [name, null], null, null, null, caseSensitive );
+ if (!attrObj) {
+ attrObj = createObj( 'attribute', {characterid:character.id, name:attrDef[0], current:'', max:''} );
+ }
+ };
+ if (attrObj) {
+ if (attrDef[3]) {
+ attrObj.setWithWorker(attrDef[1],String(attrValue));
+ } else {
+ attrObj.set(attrDef[1],String(attrValue));
+ }
+ }
+ return attrObj;
+ }
+
+ /** --------------------------- Ability Management Functions ------------------------------ **/
+
+ /**
+ * Find an ability macro with the specified name in any
+ * macro database with the specified root name, returning
+ * the database name, and the matching "ct-" object.
+ * If can't find a matching ability macro or "ct-" object
+ * then return undefined objects
+ * RED v2.044: Updated to use a database index of object IDs
+ * to speed up lookups.
+ **/
+
+ LibFunctions.abilityLookup = function( rootDB, ability, charCS, silent=false, def=true, isGM=false, trueAbility='' ) {
+
+ var charID, obj, ct, dBname, spells, items, objIndex, abilityName,
+ trueAbilityName = (trueAbility || '').dbName(),
+ source = 'charDB',
+ notFound = false,
+ abilityObj = [],
+ ctObj = [],
+ rDB = rootDB.toLowerCase().replace(/-/g,'_');
+
+ if (_.isUndefined(DBindex[rDB])) {
+ for (dBname of _.keys(DBindex)) {
+ if (rDB.startsWith(dBname)) {
+ rDB = dBname;
+ break;
+ }
+ }
+ }
+ if (!ability || ability.length==0 || ability === '-') {
+ return (!def ? new AbilityObj( rootDB, undefined, undefined, undefined) : new AbilityObj( rDB, [undefined,blankItem], [undefined,0], 'apiDB'));
+ }
+
+ do {
+ abilityName = (ability || '').dbName();
+ if (!_.isUndefined(DBindex[rDB]) && !_.isUndefined(DBindex[rDB][abilityName])) {
+ objIndex = DBindex[rDB][abilityName];
+ if (objIndex[0].length) {
+ obj = getObj('ability',objIndex[0]);
+ }
+ }
+ if (charCS && (!objIndex || (objIndex[0].length && !obj))) {
+ obj = findObjs({ type:'ability', characterid:charCS.id, name:ability });
+ if (obj && obj.length) {
+ source = 'sheet';
+ obj = obj[0];
+ objIndex = [];
+ objIndex.push(obj.id);
+ ct = findObjs({ type:'attribute', characterid:charCS.id, name:'ct-'+ability });
+ }
+ }
+ notFound = notFound || (!objIndex || (objIndex[0].length && !obj));
+ if (notFound) ability = trueAbility;
+ } while (notFound && abilityName !== trueAbilityName && ability && ability.length);
+
+ if (!objIndex || (objIndex[0].length && !obj)) {
+ if (!silent) log('Not found ability '+abilityName+' in any '+rootDB+' database');
+ return new AbilityObj( rootDB, undefined, undefined, undefined);
+ } else if (!objIndex[0].length) {
+ source = 'apiDB';
+ dBname = rootDB;
+ obj = dbNames[objIndex[2]].db[objIndex[3]];
+ obj.body = LibFunctions.parseStr(obj.body,dbReplacers);
+ abilityObj = [undefined,obj];
+ ctObj = [undefined,obj.ct];
+ } else {
+ charID = obj.get('characterid');
+ dBname = getObj('character',charID).get('name');
+ spells = dBname.startsWith(fields.MU_SpellsDB) || dBname.startsWith(fields.PR_SpellsDB) || dBname.startsWith(fields.Powers_DB);
+ items = dBname.startsWith(fields.MagicItemDB);
+ abilityObj[0] = obj;
+ ct = !ct ? getObj('attribute',objIndex[1]) : ct[0];
+ abilityObj[1] = {name:obj.get('name'),
+ type:'',
+ ct:(!ct ? 0 : ct.get('current')),
+ charge:(!ct || spells ? 'uncharged' : ct.get('max')),
+ cost:(!ct || items ? '0' : ct.get('max')),
+ body:obj.get('action')};
+ ctObj = [ct,abilityObj[1].ct];
+ };
+// if (!notFound && !isGM) abilityObj[1].body = abilityObj[1].body.replace(/{{\s*?Looks Like\s*=.*?}}/img,'');
+ return new AbilityObj( dBname, abilityObj, ctObj, source );
+ }
+
+ /*
+ * Create or update an ability on a character sheet
+ */
+
+ LibFunctions.setAbility = function( charCS, abilityName, abilityMacro, actionBar=false ) {
+
+ var abilityObj = findObjs({type: 'ability',
+ characterid: charCS.id,
+ name: abilityName},
+ {caseInsensitive:true});
+ if (!abilityObj || abilityObj.length == 0) {
+ abilityObj = createObj( 'ability', {characterid: charCS.id,
+ name: abilityName,
+ action: abilityMacro,
+ istokenaction: actionBar});
+ } else {
+ abilityObj = abilityObj[0];
+ abilityObj.set( 'action', abilityMacro );
+ abilityObj.set( 'istokenaction', actionBar );
+ }
+ return abilityObj;
+ }
+
+ /*
+ * Handle displaying an Ability Macro
+ */
+
+ LibFunctions.doDisplayAbility = function( args, selected, senderId, as, img ) {
+ if (!args) args=[];
+ if (!args[0] && selected && selected.length) {
+ args[0] = selected[0]._id;
+ } else if (!args[0] || args.length < 3) {
+ log('doDisplayAbility: invalid arguments, missing token_id or ability specification');
+ LibFunctions.sendError('Incorrect RPGMaster syntax');
+ return;
+ }
+ var tokenID = args[0],
+ dbName = args[1],
+ ability = args[2],
+ diceRoll1 = args[3] || '',
+ diceRoll2 = args[4] || '',
+ targetID = args[5] || '',
+// curToken = getObj('graphic',tokenID),
+// charCS = (curToken ? getObj('character',curToken.get('represents')) : undefined),
+ charCS = LibFunctions.getCharacter(tokenID),
+ targetToken = getObj('graphic',targetID),
+ targetCS = (targetToken ? getObj('character',targetToken.get('represents')) : undefined),
+ abObj, abilityMacro;
+
+ if (!charCS) {
+ log('doDisplayAbility: invalid token_id');
+ LibFunctions.sendError('Incorrect RPGMaster syntax');
+ return;
+ }
+
+ if (dbName.toLowerCase().includes('-db')) {
+ abObj = LibFunctions.abilityLookup( dbName, ability, charCS );
+ if (!abObj.obj) {
+ log('doDisplayAbility: invalid ability spec, '+dbName+'|'+ability);
+ LibFunctions.sendError('Incorrect RPGMaster syntax');
+ return;
+ }
+ abilityMacro = abObj.obj[1].body;
+ } else {
+ const abilityCS = findObjs({type:'character',name:dbName});
+ if (abilityCS) {
+ abObj = findObjs({type:'ability',characterid:abilityCS[0].id,name:ability});
+ }
+ if (!abObj) {
+ LibFunctions.sendError('Not found ability '+ability+' for character '+charCS.get('name'));
+ return;
+ }
+ abilityMacro = abObj[0].get('action');
+ }
+ diceRoll1 = diceRoll1 ? parseInt((diceRoll1.match(/\((\d+)\)/) || diceRoll1.match(/(\d+)/) || [0,randomInteger(20)])[1]) : randomInteger(20);
+ diceRoll2 = diceRoll2 ? parseInt((diceRoll2.match(/\((\d+)\)/) || diceRoll2.match(/(\d+)/) || [0,randomInteger(8)])[1]) : randomInteger(8);
+
+ abilityMacro = abilityMacro.replace(/\}\}\}/g,'} }}')
+ .replace(/%%diceRoll1%%/img,diceRoll1)
+ .replace(/%%diceRoll2%%/img,diceRoll2)
+ .replace(/@{selected\|token_id}/img,tokenID)
+ .replace(/@{selected/img,'@{'+charCS.get('name'));
+ if (targetToken && targetCS) {
+ let targetHP = LibFunctions.getTokenValue( targetToken, fields.token_HP, fields.HP, null, fields.Thac0_base, false );
+ let targetMaxHP = LibFunctions.getTokenValue( targetToken, fields.token_MaxHP, fields.MaxHP, null, fields.Thac0_base, false );
+ let targetAC = LibFunctions.getTokenValue( targetToken, fields.token_AC, fields.AC, fields.MonsterAC, fields.Thac0_base, false );
+ let tokenName = targetToken.get('name');
+ let targetName = targetCS.get('name');
+ let heart = abilityMacro.match(/\{\{\s*Token[_\s]Heart\s*=.*?\}\}/im);
+ if (heart) {
+ abilityMacro = abilityMacro.replace(heart[0],'{{Token_Heart='+Math.ceil(8*Math.max(0,targetHP.val)/targetMaxHP.val)+'}}');
+ }
+ abilityMacro = abilityMacro.replace(/@\{\s*target\s*\|?[^\{\}]*?\|\s*token_id\s*\}/img,targetID)
+ .replace(/(?:\[\[)?\s*(?:0\s*\+)?\s*@\{target\|?[^\{\}]*?\|hp\|max\}\s*(?:\&\{noerror\})?\s*(?:\]\])?/img,targetMaxHP.val+' ')
+ .replace(/(?:\[\[)?\s*(?:0\s*\+)?\s*@\{target\|?[^\{\}]*?\|hp\}\s*(?:\&\{noerror\})?\s*(?:\]\])?/img,targetHP.val+' ')
+ .replace(new RegExp('(?:\\[\\[)?\\s*(?:0\\s*\\+)?\\s*@\\{target\\|?[^\\{\\}]*?\\|'+targetMaxHP.name+'\\|max\\}\\s*(?:\\&\\{noerror\\})?\\s*(?:\\]\\])?','img'),targetMaxHP.val+' ')
+ .replace(new RegExp('(?:\\[\\[)?\\s*(?:0\\s*\\+)?\\s*@\\{target\\|?[^\\{\\}]*?\\|'+targetHP.name+'\\}\s*(?:\\&\\{noerror\\})?\\s*(?:\\]\\])?','img'),targetHP.val+' ')
+ .replace(/(?:\[\[)?\s*(?:0\s*\+)?\s*@\{target\|?[^\{\}]*?\|ac\}\s*(?:\&\{noerror\})?\s*(?:\]\])?/img,targetAC+' ')
+ .replace(/@\{target\|?[^\{\}]*?\|token_name\}(?:\s*\&\{noerror\})?/img,tokenName+' ');
+ let targetFields = [...abilityMacro.matchAll(/(?:\[\[)?(?:\s*0\s*\+)?\s*(@\{target\|.*?\})\s*(?:\&\{noerror\})?\s*(?:\]\])?/img)];
+ _.each(targetFields, f => abilityMacro = abilityMacro.replace(f[0],f[1]));
+ abilityMacro = abilityMacro.replace(/@\{target\|?[^\{\}]*?\|/img,'@{'+targetName+'|');
+ }
+
+ LibFunctions.sendResponse( charCS, abilityMacro, senderId, as, img, tokenID );
+ }
+
+ /*
+ * Wrap abilityLookup() with storing the ability body onto the
+ * identified character sheet, so that it is available for sending
+ * to chat under an API button
+ */
+
+ LibFunctions.getAbility = function( rootDB, name, charCS, silent, isGM, trueName ) {
+ var abObj = LibFunctions.abilityLookup( rootDB, name, charCS, silent, true, isGM, trueName ),
+ extra = false,
+ extraList = [],
+ extraDef = {};
+// if (abObj.obj && abObj.source && abObj.source !== 'sheet' && charCS) {
+// var charName = charCS.get('name');
+ if (abObj.obj) {
+ do {
+ extra = abObj.obj[1].body.match(/%{(.+?)\|(.+?)}/);
+ if (extra) {
+ if (!extraList.includes(extra[2].dbName())) {
+ extraList.push(extra[2].dbName());
+ extraDef = LibFunctions.abilityLookup( extra[1], extra[2], charCS, silent );
+ } else {
+ extraDef.obj = undefined;
+ }
+ if (extraDef.obj) {
+ abObj.obj[1].body = abObj.obj[1].body.replace(/%{(.+?)\|(.+?)}/,extraDef.obj[1].body);
+ } else {
+ abObj.obj[1].body = abObj.obj[1].body.replace(/%{(.+?)\|(.+?)}/,'');
+ }
+ }
+ } while (extra && extraDef.obj);
+
+ if (!isGM && trueName && trueName.length && (name.dbName() === trueName.dbName())) {
+ abObj.obj[1].body = abObj.obj[1].body.replace(/{{\s*?Looks\s?Like\s*=/img,'{{Appearance=');
+ }
+ if (charCS) {
+ if (trueName && trueName.length && name.dbName() !== trueName.dbName()) {
+ let cmd = '{{GM Info=[Reveal Now](!magic --button GM-ResetSingleMI|'+charCS.id+'|'+name
+ + ' --message gm|'+charCS.id+'|Revealing '+trueName.dispName()+'|The item '+trueName.dispName()+' which was hidden as '+name.dispName()+' has been revealed)';
+ if (/{{\s*GM\s?Info\s*=/im.test(abObj.obj[1].body)) {
+ abObj.obj[1].body = abObj.obj[1].body.replace(/{{\s*GM\s?Info\s*=([^\[])/im,(cmd + ' $1'));
+ } else {
+ abObj.obj[1].body += cmd + '}}';
+ }
+ }
+ abObj.obj[0] = LibFunctions.setAbility( charCS, name, abObj.obj[1].body );
+ LibFunctions.setAttr( charCS, [fields.CastingTimePrefix[0]+name,'current'], abObj.obj[1].ct );
+ LibFunctions.setAttr( charCS, [fields.CastingTimePrefix[0]+name,'max'], abObj.obj[1].charge );
+ abObj.dB = charCS.get('name');
+ }
+ }
+ return abObj;
+ }
+
+ /** -------------------------------------------- send messages to chat ----------------------------------------- **/
+
+ LibFunctions.parseTemplate = function( txt ) {
+// return LibFunctions.parseOutput( '', '', '', txt, null, null, null, false );
+ };
+
+ LibFunctions.redisplayOutput = function(senderId) {
+ if (senderId && senderId.length && !_.isUndefined(lastMsg[senderId])) {
+ let args = [...lastMsg[senderId]];
+ if (args.length > 3) {
+ return LibFunctions.parseOutput( args[0], args[1], args[2], args[3], senderId );
+ }
+ }
+ }
+
+ /*
+ * Parse the standard Roll Template structure for RPGMaster
+ * templates and return the converted text for display in the
+ * chat window.
+ */
+
+ LibFunctions.parseOutput = function( as, preamble, template, txt, senderId ) {
+
+ var isGM = false;
+ if (senderId && senderId.length) {
+ for (const playerId of senderId.split(',')) {
+ lastMsg[playerId] = arguments;
+ isGM = isGM || playerIsGM(playerId);
+ }
+ }
+
+ txt = txt.replace(/}}\s*?k/img,'} }k')
+ .replace(/{{=/img,'{{ =')
+ .replace(/</img,'<')
+ .replace(/>/img,'>')
+ .replace(/{{\s*}}/img,'');
+
+ var colours, colourSet;
+
+ switch (template.toLowerCase()) {
+ case 'rpgmattack':
+ colourSet = 'attack';
+ break;
+ case 'rpgmweapon':
+ case 'rpgmammo':
+ colourSet = 'weapon';
+ break;
+ case 'rpgmpotion':
+ colourSet = 'potion';
+ break;
+ case 'rpgmspell':
+ case 'rpgmitemspell':
+ case 'rpgmwandspell':
+ case 'rpgmscroll':
+ colourSet = 'spell';
+ break;
+ case 'rpgmmenu':
+ colourSet = 'menu';
+ break;
+ case 'rpgmmessage':
+ colourSet = 'message';
+ break;
+ case 'rpgmwarning':
+ colourSet = 'warning';
+ break;
+ case 'rpgmarmour':
+ case 'rpgmitem':
+ case 'rpgmring':
+ case 'rpgmwand':
+ case 'rpgmclass':
+ case 'rpgmdefault':
+ default:
+ colourSet = 'def';
+ break;
+ }
+ if (_.isUndefined(state.MagicMaster) || _.isUndefined(state.attackMaster)) {
+ colours = Object.create(pallet.plain[colourSet]);
+ } else if (!senderId || _.isUndefined(state.MagicMaster.playerConfig) || _.isUndefined(state.MagicMaster.playerConfig[senderId])) {
+ colours = Object.create((state.attackMaster.fancy || state.MagicMaster.fancy) ? pallet.fancy[colourSet] : pallet.plain[colourSet]);
+ } else {
+ let config = state.MagicMaster.playerConfig[senderId];
+ colours = Object.create(config.menuImages ? pallet.fancy[colourSet] : (config.menuDark ? pallet.dark[colourSet] : pallet.plain[colourSet]));
+ }
+ if (template) {
+ const txtObj = _.object([...txt.replace(/[\r\n]/g,'').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1)).map(v => [v[0].dbName(),v[1]]));
+ _.each( txtObj, (t,k) => {
+ if (!_.isUndefined(colours[k])) {
+ colours[k] = t;
+ txt = txt.replace(new RegExp(`{{\\s*${k}\\s*=.*?}}`,'img'),'');
+ }
+ });
+ };
+ const outerFrame = '';
+ const endOuterFrame = '
';
+ const headerFrame = '';
+ const endHeaderFrame = ' |
';
+ const header1 = '';
+ const endHeader1 = '';
+ const header2 = '';
+ const endHeader2 = '';
+ const subtitle1 = '
';
+ const endSubtitle1 = '';
+ const subtitle2 = '
';
+ const endSubtitle2 = '';
+ const settings = '';
+
+ const bodyFrame = '';
+ const fullBodyFrame = '';
+ const lastBodyFrame = '';
+ const endBodyFrame = ' ';
+ const row1col = ['',
+ ' '];
+ const rowResult = ['',
+ ' '];
+ const endRowResult = ' '
+ const endRow1col = ' ';
+ const rowHeader = ' ';
+ const endRowHeader = ' | ';
+ const rowBodyC = ' ';
+ const endRowBodyC = ' | ';
+ const rowBody = ' ';
+ const endRowBody = ' | ';
+ const row1 = ' ';
+ const endRow1 = ' | ';
+ const row1C = ' ';
+ const endRow1C = ' | ';
+ const row2col = [' ',
+ ' '];
+ const endRow2col = ' ';
+ const rowL = ' ';
+ const endRowL = ' | ';
+ const rowR = ' ';
+ const endRowR = ' | ';
+ const rowC = ' ';
+ const endRowC = ' | ';
+ const row2 = ' ';
+ const endRow2 = ' | ';
+ const rowC2 = ' ';
+ const endRowC2 = ' | ';
+ const titleDmgSM = ' '+colours.dmgslabel+' | ';
+ const rowDmgSM = ' ';
+ const endRowDmgSM = ' | ';
+ const titleAC = ' AC Hit | ';
+ const rowAC = ' ';
+ const endRowAC = ' | ';
+ const rowType = ' ';
+ const endRowType = ' | ';
+ const titleDmgL = ' '+colours.dmgllabel+' | ';
+ const rowDmgL = ' ';
+ const endRowDmgL = ' | ';
+ const sImg = ' '
+ const pImg = ' '
+ const bImg = ' '
+ const rowTargetAC = ' Target | ';
+ const endRowTargetAC = ' | AC | ';
+ const rowTargetSAC = ' ';
+ const endRowTargetSAC = ' | ';
+ const rowTargetPAC = ' ';
+ const endRowTargetPAC = ' | ';
+ const rowTargetBAC = ' ';
+ const endRowTargetBAC = ' | ';
+ const titleTargetHP = ' Target HP | '
+ const rowTargetHP = ' ';
+ const endTableStyle = ' | ';
+
+ const addDescs = function( txtObj, j ) {
+ let content = '';
+ if (!_.isUndefined(txtObj.desc)) content += (row1col[(j++)%2]+row1+ txtObj.desc +endRow1+endRow1col);
+ for (let i=1; i<=9; ++i) {
+ if (!_.isUndefined(txtObj['desc'+i])) content += (row1col[(j++)%2]+row1+ txtObj['desc'+i] +endRow1+endRow1col);
+ };
+ return content;
+ };
+
+ const RPGMattack = function( txt ) {
+ const attkDefaults = {title:'', name:'', subtitle:'', ac_hit:'', target_ac:'', attk_type:'', target_sac:'', target_pac:'', target_bac:'', dmg_s:'', dmg_l:'', target_hp:'', target_maxhp:''};
+ const txtObj = _.object([...txt.replace(/[\r\n]/g,'').replace(/\}\}\}/g,'} }}').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1)).map(v => [v[0].replace(/[-\s]/g,'_').toLowerCase(),v[1]]));
+ const dice_roll = parseInt((txtObj.ac_hit.match(/(\d+)\[Dice roll\]/i) || ['',''])[1]);
+ const hasDescs = /{{\s*desc\d?\s*=/im.test(txt);
+ _.defaults(txtObj,attkDefaults);
+ txtObj.attk_type = txtObj.attk_type.toLowerCase();
+ var content = outerFrame;
+ if (txtObj.title.length || txtObj.name.length) {
+ content += headerFrame
+ +header1+ txtObj.title+txtObj.name +endHeader1
+ +(txtObj.subtitle ? (subtitle1+ txtObj.subtitle +endSubtitle1) : '')
+ +settings
+ +endHeaderFrame;
+ }
+ if (txtObj.ac_hit != '') {
+ content += ((txtObj.crit_roll || txtObj.fumble_roll || txtObj.target_ac != '' || txtObj.result) ? bodyFrame : lastBodyFrame)
+ +row1col[0]
+ +titleDmgSM
+ +rowAC+ txtObj.ac_hit +endRowAC
+ +titleDmgL
+ +endRow1col
+ +row1col[1]
+ +rowDmgSM+ txtObj.dmg_s +endRowDmgSM
+ +rowDmgL+ txtObj.dmg_l +endRowDmgL
+ +endRow1col
+ +row1col[0]
+ +titleAC
+ +endRow1col
+ +row1col[1]
+ +rowType+ [sImg,pImg,bImg].filter((e,i) => txtObj.attk_type.includes(['s','p','b'][i])).join('') +endRowType
+ +endRow1col
+ +endBodyFrame;
+ }
+ if ((txtObj.crit_roll || txtObj.fumble_roll) && !isNaN(dice_roll)) {
+ const crit_roll = parseInt(txtObj.crit_roll);
+ const fumble_roll = parseInt(txtObj.fumble_roll);
+ const crit = (crit_roll && (crit_roll <= dice_roll));
+ const fumble = (fumble_roll && (fumble_roll >= dice_roll));
+ if (crit || fumble) {
+ content += ((txtObj.target_ac != '' || txtObj.result) ? bodyFrame : lastBodyFrame)
+ +(!crit ? '' : (rowResult[0]+rowC+ (txtObj.crit || 'Critical Hit!') +endRowC+endRowResult))
+ +(!fumble ? '' : (rowResult[1]+rowC+ (txtObj.fumble || 'Fumbled!') +endRowC+endRowResult))
+ +endBodyFrame;
+ }
+ }
+ if (txtObj.target_ac != '') {
+ const target_hp = parseInt(txtObj.target_hp.match(/[-+]?\d+/));
+ const target_maxhp = parseInt(txtObj.target_maxhp.match(/[-+]?\d+/));
+ const heart_url = !(isNaN(target_hp) || isNaN(target_maxhp)) ? heart[Math.min(Math.ceil(8*Math.max(target_hp,0)/target_maxhp),8)] : '';
+ content += ((txtObj.result) ? bodyFrame : lastBodyFrame)
+ +row1col[0]
+ +rowTargetAC+ txtObj.target_ac +endRowTargetAC
+ +titleTargetHP
+ +endRow1col
+ +row1col[1]
+ +rowTargetSAC+ txtObj.target_sac +endRowTargetSAC
+ +rowTargetPAC+ txtObj.target_pac +endRowTargetPAC
+ +rowTargetBAC+ txtObj.target_bac +endRowTargetBAC
+ +rowTargetHP + 'background-image: url('+heart_url+');">' +endRowTargetHP
+ +endRow1col
+ +endBodyFrame;
+ }
+ if (txtObj.result) {
+ let result;
+ const test = txtObj.result.match(/([\w\s_.+-]+?|[-+]?[\d.]+?)((?:<=|>=|<|>|=|<>|!=))(.+)/);
+ if (test) {
+ const field1 = test[1].replace(/[-\s]/g,'_').toLowerCase();
+ const field2 = test[3].replace(/[-\s]/g,'_').toLowerCase();
+ const value1 = (/^[-+]?[\d.]+/.test(test[1])|| _.isUndefined(txtObj[field1])) ? parseFloat(test[1]) : parseFloat(txtObj[field1].match(/[-+]?[\d.]+/));
+ const value2 = (/^[-+]?[\d.]+/.test(test[3])|| _.isUndefined(txtObj[field2])) ? parseFloat(test[3]) : parseFloat(txtObj[field2].match(/[-+]?[\d.]+/));
+ switch (test[2]) {
+ case '=': result = value1 == value2; break;
+ case '<': result = value1 < value2; break;
+ case '>': result = value1 > value2; break;
+ case '<=': result = value1 <= value2; break;
+ case '>=': result = value1 >= value2; break;
+ case '<>': result = value1 != value2; break;
+ case '!=': result = value1 != value2; break;
+ default: result = false;
+ }
+ content += (hasDescs ? bodyFrame : lastBodyFrame)
+ +rowResult[result ? 0 : 1]+rowC+''+ (result ? 'Success' : 'Failure') +''+endRowC+endRowResult
+ +endBodyFrame;
+// log('RPGMattack: successcmd = '+txtObj.successcmd);
+ if (txtObj.successcmd && txtObj.successcmd.length && result) {
+ LibFunctions.sendAPI(txtObj.successcmd);
+ } else if (txtObj.failcmd && txtObj.failcmd.length && !result) {
+ LibFunctions.sendAPI(txtObj.failcmd);
+ }
+ }
+ }
+ if (hasDescs) {
+ content += lastBodyFrame
+ +addDescs(txtObj,1)
+ +endBodyFrame;
+ }
+ content += endOuterFrame;
+ return content;
+ };
+
+ const RPGMspell = function( txt ) {
+ const spellDefaults = {title:'', name:'', splevel:'', school:'', range:'', components:'', duration:'', time:'', aoe:'', save:'', effects:''};
+ let k=1;
+ const txtObj = _.object([...txt.replace(/[\r\n]/g,'').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1)).map(v => [v[0].replace(/[-\s]/g,'_').toLowerCase(),v[1]]));
+ const isLooksLike = !isGM && !!txtObj.looks_like;
+ _.defaults(txtObj,spellDefaults);
+ const content = outerFrame
+ +headerFrame
+ +header2+ txtObj.title+(!isLooksLike ? txtObj.name : '')+endHeader2
+ +(!isLooksLike ? (subtitle2+ txtObj.splevel +' * '+ txtObj.school +endSubtitle2) : '')
+ +settings
+ +endHeaderFrame
+ +lastBodyFrame
+ +(!isLooksLike ? (
+ row2col[++k%2]+rowL+'Range '+ txtObj.range +endRowL
+ +rowR+'Components '+ txtObj.components +endRowR+endRow2col
+ +row2col[++k%2]+rowL+'Duration '+ txtObj.duration +endRowL
+ +rowR+'Casting Time '+ txtObj.time +endRowR+endRow2col
+ +row2col[++k%2]+rowL+'Area of Effect '+ txtObj.aoe +endRowL
+ +rowR+'Saving Throw '+ txtObj.save +endRowR+endRow2col
+ +(txtObj.healing ? (row2col[++k%2]+rowC2+'Healing: '+ txtObj.healing +endRowC2+endRow2col) : '')
+ +(txtObj.damage ? (row2col[++k%2]+rowC2+'Damage: '+ txtObj.damage +endRowC2+endRow2col) : '')
+ +(txtObj.reference ? (row2col[++k%2]+rowC2+'Reference: '+ txtObj.reference +endRowC2+endRow2col) : '')
+ +(txtObj.materials ? (row2col[++k%2]+rowC2+'Materials: '+ txtObj.materials +endRowC2+endRow2col) : '')
+ +(txtObj.use ? (row2col[++k%2]+row2+'Use: '+ txtObj.use +endRow2+endRow2col) : '')
+ +(isGM && txtObj.gm_info ? (row2col[++k%2]+row2+'GM Info: '+ txtObj.gm_info +endRow2+endRow2col) : '')
+ ) : '')
+ +(txtObj.looks_like || txtObj.appearance ? (row2col[++k%2]+row2+(!isLooksLike ? 'Looks Like: ' : '')+ (txtObj.looks_like ? txtObj.looks_like : txtObj.appearance) +endRow2+endRow2col) : '')
+ +(!isLooksLike ? (
+ row2col[++k%2]+row2+'Effects: '+ txtObj.effects +endRow2+endRow2col
+ + addDescs(txtObj,++k)
+ ) : '');
+ +endBodyFrame
+ +endOuterFrame;
+ return content;
+ }
+
+ const RPGMmessage = function( txt ) {
+
+ const txtObj = _.object([...txt.replace(/[\r\n]/g,'').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1)).map(v => [v[0].replace(/[-\s]/g,'_').toLowerCase(),v[1]]));
+ let content = outerFrame;
+ if (txtObj.name || txtObj.title) {
+ content += headerFrame
+ +header1+ (txtObj.title || '')+(txtObj.name || '') +endHeader1
+ +settings
+ +endHeaderFrame
+ +lastBodyFrame;
+ } else {
+ content += fullBodyFrame;
+ }
+ content += addDescs(txtObj,1)
+ +endBodyFrame
+ +endOuterFrame;
+ return content;
+ }
+
+ const RPGMdefault = function( txt ) {
+
+ const defDefaults = {title:'', name:''};
+ const txtObj = template ? _.object([...txt.replace(/[\r\n]/g,'').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1))) : undefined;
+ const isLooksLike = !isGM && /{{\s*Looks\s?Like\s*=.*?}}/im.test(txt);
+ _.defaults(txtObj,defDefaults);
+ let content = outerFrame
+ +headerFrame
+ +header1+ txtObj.title+(!isLooksLike ? txtObj.name : '')+endHeader1
+ +(txtObj.subtitle && !isLooksLike ? (subtitle1+ txtObj.subtitle +endSubtitle1) : '')
+ +settings
+ +endHeaderFrame;
+ content += lastBodyFrame;
+ let j=1;
+ _.each(txtObj,(t,k) => {
+ t = t.replace(/\/img,tableStyle);
+ t = t.replace(/\<\/table\>/img,endTableStyle);
+ txtObj[k] = t;
+ if (!t || !t.length) return;
+ if (k.toLowerCase().replace(/\s/g,'') === 'lookslike') {
+ if (!isGM) {
+ content += (row2col[(j++)%2]+row2+ t +endRow2+endRow2col);
+ } else {
+ content += (row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col);
+ }
+ } else if (isLooksLike) {
+ return;
+ } else if (k.toLowerCase() === 'result') {
+ let result;
+ const test = t.match(/([\w\s_.+-]+?|[-+]?[\d.]+?)((?:<=|>=|<|>|=|<>|!=))(.+)/);
+ if (test) {
+ const value1 = (/^[-+]?[\d.]+/.test(test[1])|| _.isUndefined(txtObj[test[1]])) ? parseFloat(test[1]) : parseFloat(txtObj[test[1]].match(/[-+]?[\d.]+/));
+ const value2 = (/^[-+]?[\d.]+/.test(test[3])|| _.isUndefined(txtObj[test[3]])) ? parseFloat(test[3]) : parseFloat(txtObj[test[3]].match(/[-+]?[\d.]+/));
+ switch (test[2]) {
+ case '=': result = value1 == value2; break;
+ case '<': result = value1 < value2; break;
+ case '>': result = value1 > value2; break;
+ case '<=': result = value1 <= value2; break;
+ case '>=': result = value1 >= value2; break;
+ case '<>': result = value1 != value2; break;
+ case '!=': result = value1 != value2; break;
+ default: result = false;
+ }
+ content += rowResult[result ? 0 : 1]+row1C+''+ (result ? 'Success' : 'Failure') +''+endRow1C+endRowResult;
+ }
+ if (txtObj.successcmd && txtObj.successcmd.length && result) {
+ LibFunctions.sendAPI(txtObj.successcmd);
+ } else if (txtObj.failcmd && txtObj.failcmd.length && !result) {
+ LibFunctions.sendAPI(txtObj.failcmd);
+ }
+ } else if (k.toLowerCase().startsWith('section')) {
+ content += row1col[(j++)%2]+row1C+ t +endRow1C+endRow1col;
+ } else if (k.toLowerCase().replace(/\s/g,'') === 'gminfo') {
+ if (isGM) content += (row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col);
+ } else {
+ content += (['name','title','subtitle'].includes(k.toLowerCase().replace(/\s/g,'')) || k.toLowerCase().startsWith('desc')) ? '' : (row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col);
+ }
+ });
+ content += (isLooksLike ? '' : addDescs(txtObj,j))
+ + endBodyFrame + endOuterFrame;
+ return content;
+ }
+
+ let content;
+ switch (template.toLowerCase()) {
+ case 'rpgmattack':
+ content = RPGMattack( txt );
+ break;
+ case 'rpgmspell':
+ case 'rpgmpotion':
+ case 'rpgmitemspell':
+ case 'rpgmwandspell':
+ case 'rpgmscroll':
+ content = RPGMspell( txt );
+ break;
+ case 'rpgmmessage':
+ content = RPGMmessage( txt );
+ break;
+ case 'rpgmweapon':
+ case 'rpgmammo':
+ case 'rpgmmenu':
+ case 'rpgmarmour':
+ case 'rpgmitem':
+ case 'rpgmring':
+ case 'rpgmwand':
+ case 'rpgmclass':
+ case 'rpgmwarning':
+ case 'rpgmdefault':
+ content = RPGMdefault( txt );
+ break;
+ default:
+ content = (template ? '&{template:'+template+'}' : '' ) + txt;
+ break;
+ }
+ content = (content[0] === '!' ? '' : preamble) + content;
+ sendChat(as?as:defaultAs,content,null,{noarchive:!archive, use3d:use3Ddice});
+ return content;
+ }
+
+ /*
+ * Determine who to send a Response to: use who controls
+ * the character - if no one or if none of the controlling
+ * players are on-line send the response to the GM
+ */
+
+ LibFunctions.sendToWho = function(charCS,senderId,makePublic=false,embedded=false) {
+
+ var to, controlledBy, players, viewerID, isPlayer=false;
+ controlledBy = charCS.get('controlledby');
+ if (controlledBy.length > 0) {
+ controlledBy = controlledBy.split(',');
+ viewerID = (state.roundMaster && state.roundMaster.viewer && state.roundMaster.viewer.is_set) ? (state.roundMaster.viewer.pid || null) : null;
+ players = controlledBy.filter(id => id != viewerID);
+ if (players.length) {
+ isPlayer = _.some( controlledBy, function(playerID) {
+ players = findObjs({_type: 'player', _id: playerID, _online: true});
+ return (players && players.length > 0);
+ });
+ };
+ };
+ if (controlledBy.includes('all')) {
+ to = '';
+ } else if (playerIsGM(senderId) || !charCS || controlledBy.length == 0 || !isPlayer) {
+ to = embedded ? '/w gm ' : '/w gm ';
+ } else if (makePublic) {
+ to = '';
+ } else {
+ to = (embedded ? ('/w "'+charCS.get('name')+'" ') : ('/w "' + charCS.get('name') + '" '));
+ }
+ return to;
+ }
+
+ /**
+ * Insert a whisper into a body with a template.
+ * If no template, inserts the whisper at the start of
+ * the first line not starting with an API call.
+ **/
+
+ LibFunctions.insertWhisper = function(to, msg='') {
+ let splitMsg = msg.match(/([^]*?)^.*?((?:&|\\amp|\\amp;){template:.*)/msi);
+ if (!splitMsg || !splitMsg.length > 2) return to+' '+msg;
+ return splitMsg[1]+'\n'+to+' '+splitMsg[2];
+ }
+
+ /**
+ * Send public message with 3d dice rolls (if enabled)
+ */
+
+ LibFunctions.sendPublic = function(msg,charCS) {
+ if (!msg)
+ {return undefined;}
+ var who;
+
+ if (charCS) {
+ who = 'character|'+charCS.id;
+ } else {
+ who = '';
+ }
+ sendChat(who,msg,null,{use3d:true});
+ };
+
+ /**
+ * Send API command to chat
+ */
+ LibFunctions.sendAPI = function(msg, senderId, from='') {
+ var as;
+ if (!msg) {
+ log('sendMagicAPI: no msg');
+ return undefined;
+ }
+ if (!senderId || senderId.length == 0) {
+ as = '';
+ } else {
+ as = 'player|' + senderId;
+ }
+ sendChat(as,msg, null,{noarchive:!archive, use3d:false});
+ };
+
+ /**
+ * Send locally parsed feedback to the GM only!
+ */
+ LibFunctions.sendFeedback = function(msg,as,img) {
+ if (!msg)
+ {return;}
+ var content = '/w GM '
+ + ''
+ + ' '
+ + ' ';
+ sendChat((as?as:defaultAs),content+msg,null,{noarchive:!archive}); //,use3d:false
+ };
+
+ /**
+ * Sends a response to everyone who controls the character
+ * RED: v0.003 Check the player(s) controlling the character are valid for this campaign
+ * if they are not, send to the GM instead - Transmogrifier can introduce invalid IDs
+ * Also check if the controlling player(s) are online. If they are not
+ * assume the GM is doing some testing and send the message to them.
+ */
+
+ LibFunctions.sendResponse = function(charCS,msg,senderId,as,img) {
+ if (!msg)
+ {return;}
+ if (!charCS || (senderId && playerIsGM(senderId))) {
+ LibFunctions.sendFeedback( msg, as, img );
+ } else {
+ var content = LibFunctions.sendToWho(charCS,senderId)
+ + ''
+ + ' '
+ + ' ';
+ sendChat((senderId ? 'player|'+senderId : charCS.get('name')),content+msg,null,{noarchive:!archive, use3d:false});
+ }
+ };
+
+ /*
+ * Send a message to the player (rather than the character)
+ */
+
+ LibFunctions.sendResponsePlayer = function(pid,msg,as,img) {
+ LibFunctions.sendResponseError(pid,msg,as,img);
+ return;
+ }
+
+ /*
+ * Send an error message to the identified player.
+ * If that player is not online, send to the GM
+ */
+
+ LibFunctions.sendResponseError = function(pid,msg,as,img) {
+ if (!pid || !msg)
+ {return null;}
+ var player = getObj('player',pid),
+ to;
+ if (player && player.get('_online')) {
+ to = '/w "' + player.get('_displayname') + '" ';
+ } else {
+ to = '/w gm ';
+ }
+ var content = to
+ + ''
+ + ' '
+ + ' &{template:'+fields.warningTemplate+'}{{title=Warning!}}{{desc='+msg+'}}';
+ sendChat((as?as:defaultAs),content,null,{noarchive:false, use3d:false});
+ };
+
+ /*
+ * Send to all players other than those that control the specified character
+ * and/or other than the specified player
+ */
+
+ LibFunctions.sendToOthers = function(pid,msg,as,img,charCS) {
+ if (!msg || (!pid && !charCS))
+ {return null;}
+ let controllers = charCS ? charCS.get('controlledby').split(',') : [];
+ let players = filterObjs(obj => {
+ if (obj.get('_type') != 'player' || obj.id == pid) return false;
+ if (controllers.includes(obj.id)) return false;
+ return obj.get('_online');
+ });
+ _.each(players, p => LibFunctions.sendResponsePlayer(p,msg,as,img));
+ };
+
+ /**
+ * Send an error
+ */
+
+ LibFunctions.sendError = function(msg) {
+ setTimeout(()=>{
+ var content = '/w GM '
+ + ''
+ + ' '
+ + ' '
+ + ''+msg+'';
+
+ sendChat(defaultAs,content,null,{noarchive:false, use3d:false});
+ log('RPGMaster error: '+msg);
+ },500);
+ };
+
+ /**
+ * Pare a message with ^^...^^ parameters in it and send to chat
+ * This allows character and token names for selected characters to be sent
+ * Must be called with a validated tokenID
+ */
+
+ LibFunctions.sendParsedMsg = function( tid, msg, senderId, msgFrom, t2id ) {
+ var cid, tname, charCS, cname, curToken,
+ parsedMsg = msg;
+
+ curToken = getObj( 'graphic', tid );
+ tname = (curToken ? curToken.get('name') : '');
+ cid = (curToken ? curToken.get('represents') : '');
+ charCS = getObj('character',cid);
+ cname = (charCS ? charCS.get('name') : '');
+
+ parsedMsg = parsedMsg.replace( /\^\^cid\^\^/gi , cid );
+ parsedMsg = parsedMsg.replace( /\^\^tid\^\^/gi , tid );
+ parsedMsg = parsedMsg.replace( /\^\^cname\^\^/gi , cname );
+ parsedMsg = parsedMsg.replace( /\^\^tname\^\^/gi , tname );
+
+ if (t2id) {
+ curToken = getObj( 'graphic', t2id );
+ tname = curToken.get('name');
+ cid = curToken.get('represents');
+ charCS = getObj('character',cid);
+ cname = charCS.get('name');
+
+ parsedMsg = parsedMsg.replace( /\^\^c2id\^\^/gi , cid );
+ parsedMsg = parsedMsg.replace( /\^\^t2id\^\^/gi , t2id );
+ parsedMsg = parsedMsg.replace( /\^\^c2name\^\^/gi , cname );
+ parsedMsg = parsedMsg.replace( /\^\^t2name\^\^/gi , tname );
+ }
+ LibFunctions.sendResponse( charCS, parsedMsg, senderId, msgFrom, null );
+ };
+
+ /*
+ * Check to see if a command string includes a gm roll query. If so,
+ * convert it to a normal roll query and send it to the GM to answer.
+ * Return true if a gm query has been found.
+ */
+
+ LibFunctions.sendGMquery = function( api, command, senderId ) {
+ var rollQuery;
+ if (command.toLowerCase().includes('gm{')) {
+ while ((rollQuery = command.match(/gm{.+?}/i))) {
+ if (!rollQuery || !rollQuery.length) break;
+ rollQuery = rollQuery[0].replace(/gm{/i,'?{').replace(/\//g,'|');
+ command = command.replace(/gm{.+?}/i,rollQuery);
+ };
+ LibFunctions.sendFeedback( '&{template:'+fields.warningTemplate+'}{{title=DM Selection}}{{desc=As DM, you need to make [selections](!'+api+' --'+command+') for '+getObj('player',senderId).get('_displayname')+'. Press the button and the selections and their reasons will be presented to you in Roll Querys in the centre of the screen.}}');
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+
+ /* ------------------------------- Character Sheet Database Management -------------------------- */
+
+ /*
+ * Check the version of a Character Sheet database against
+ * the current version in the API. Return true if needs updating
+ */
+
+ LibFunctions.checkDBver = function( dbFullName, dbObj, silent ) {
+
+ dbFullName = dbFullName.replace(/_/g,'-');
+
+ var dbCS = findObjs({ type:'character', name:dbFullName },{caseInsensitive:true}),
+ dbVersion = 0.0,
+ msg, versionObj;
+
+ if (!dbCS || !dbCS.length) return true;
+
+ dbCS = dbCS[0];
+ dbVersion = parseFloat(LibFunctions.attrLookup( dbCS, fields.dbVersion ) || dbVersion);
+
+ if (dbVersion < (parseFloat(dbObj.version) || 0)) {log('checkDBver: dB '+dbFullName+' API version='+(parseFloat(dbObj.version) || 0)+', CS version='+dbVersion); return true;}
+
+ msg = dbFullName+' v'+dbVersion+' not updated as is already latest version';
+ if (!silent) LibFunctions.sendFeedback(msg,fields.feedbackName);
+ return false;
+ }
+
+ /*
+ * A function to read the abilities of a database character sheet
+ * and write them to a handout, so they can be cut&pasted to an API
+ * for saving as a new version.
+ */
+
+ LibFunctions.saveDBtoHandout = function( dbName, version ) {
+
+ var dbCS = findObjs({ type: 'character', name: dbName })[0] || undefined,
+ objDef,
+ objHeader = '',
+ foundItems = [],
+ dbHandout,csDBlist;
+
+ var encodeStr = (str,encoders=dbEncoders) => encoders.reduce((m, rep) => m.replace(rep[0], rep[1]), str);
+
+ if (!dbCS) {
+ LibFunctions.sendError('Database '+dbName+' not found');
+ return undefined;
+ }
+ if (!version || !version.length) {
+ version = (parseFloat(LibFunctions.attrLookup( dbCS, fields.dbVersion ) || '1.0') + 0.01).toFixed(2).toString();
+ } else if (version === '=') {
+ version = parseFloat(LibFunctions.attrLookup( dbCS, fields.dbVersion ) || '1.0');
+ }
+ dbHandout = findObjs({ type: 'handout', name: dbName+'-object v'+version });
+
+ if (!dbHandout || !dbHandout.length) {
+ dbHandout = createObj('handout',{name:(dbName+'-object v'+version)});
+ } else {
+ dbHandout = dbHandout[0];
+ }
+
+ objHeader = 'avatar:\''+dbCS.get('avatar')+'\', '
+ + 'version:'+version+', ';
+ objDef = 'db:[';
+ csDBlist = findObjs({ type: 'ability', characterid: dbCS.id });
+
+ _.each( _.sortBy(csDBlist,item => item.get('name')), function( item ) {
+ let itemName = item.get('name');
+ if (foundItems.includes(itemName)) return;
+ foundItems.push(itemName);
+
+ let objBody = encodeStr(item.get('action')),
+ objCT = (objBody.match(reDataSpeed) || ['',0])[1],
+ objChg = (objBody.match(reDataCharge) || ['','uncharged'])[1],
+ objCost = (objBody.match(reDataCost) || ['',0])[1],
+ objType = '',
+ specs = objBody.match(/}}\s*?specs\s*?=(.*?){{/im);
+
+ specs = specs ? [...('['+specs[0]+']').matchAll(reSpecClass)] : [];
+ for (let i=0; i < specs.length; i++) {
+ objType += (objType && objType.length) ? ('|' + specs[i][1]) : specs[i][1];
+ }
+
+ objBody = objBody.replace(/template:2Edefault/i,'template:\'+fields.CSdefaultTemplate+\'')
+ .replace(/template:2Espell/i,'template:\'+fields.CSspellTemplate+\'')
+ .replace(/template:2Eattack/i,'template:\'+fields.CSweaponTemplate+\'')
+ .replace(/template:RPGMdefault/i,'template:\'+fields.defaultTemplate+\'')
+ .replace(/template:RPGMspell/i,'template:\'+fields.spellTemplate+\'')
+ .replace(/template:RPGMweapon/i,'template:\'+fields.weaponTemplate+\'')
+ .replace(/template:RPGMpotion/i,'template:\'+fields.potionTemplate+\'')
+ .replace(/template:RPGMattack/i,'template:\'+fields.targetTemplate+\'')
+ .replace(/template:RPGMammo/i,'template:\'+fields.ammoTemplate+\'')
+ .replace(/template:RPGMarmour/i,'template:\'+fields.armourTemplate+\'')
+ .replace(/template:RPGMitem/i,'template:\'+fields.itemTemplate+\'')
+ .replace(/template:RPGMitemSpell/i,'template:\'+fields.itemSpellTemplate+\'')
+ .replace(/template:RPGMring/i,'template:\'+fields.ringTemplate+\'')
+ .replace(/template:RPGMscroll/i,'template:\'+fields.scrollTemplate+\'')
+ .replace(/template:RPGMwand/i,'template:\'+fields.wandTemplate+\'')
+ .replace(/template:RPGMwandSpell/i,'template:\'+fields.wandSpellTemplate+\'')
+ .replace(/template:RPGMmessage/i,'template:\'+fields.messageTemplate+\'')
+ .replace(/template:RPGMwarning/i,'template:\'+fields.warningTemplate+\'')
+ .replace(/template:RPGMclass/i,'template:\'+fields.classTemplate+\'');
+
+ objDef += '{name:\''+itemName+'\','
+ + 'type:\''+objType+'\','
+ + 'ct:\''+objCT+'\','
+ + 'charge:\''+objChg+'\','
+ + 'cost:\''+objCost+'\','
+ + 'body:\''+objBody+'\'}, ';
+ });
+ objDef += ']}, ';
+ dbHandout.set('notes',objHeader+objDef);
+ LibFunctions.sendFeedback('Extracted '+dbName+' v'+version,fields.feedbackName);
+ LibFunctions.setAttr( dbCS, fields.dbVersion, version );
+ return dbHandout;
+ }
+
+ /*
+ * Check the version of a Character Sheet database and, if
+ * it is earlier than the static data held in this API, update
+ * it to the latest version.
+ */
+
+ LibFunctions.buildCSdb = function( dbFullName, dbObj, typeList, silent ) {
+
+ dbFullName = dbFullName.replace(/_/g,'-');
+
+ const spells = dbObj.type.includes('spell') || dbObj.type.includes('power'),
+ charClass = dbObj.type.includes('class'),
+ rootDB = dbObj.root.toLowerCase();
+
+ var dbVersion = 0.0,
+ dbCS = findObjs({ type:'character', name:dbFullName },{caseInsensitive:true}),
+ errFlag = false,
+ lists = {},
+ foundItems = [],
+ csDBlist, specs, objType, objBody,
+ msg, versionObj, curDB;
+
+ if (LibFunctions.checkDBver( dbFullName, dbObj, silent )) {
+
+ if (dbCS && dbCS.length) {
+ let abilities = findObjs({ _type:'ability', _characterid:dbCS[0].id });
+ _.each( abilities, a => a.remove() );
+ dbCS = dbCS[0];
+ } else {
+ dbCS = createObj( 'character', {name:dbFullName} );
+ }
+
+ let sorted = _.sortBy(dbObj.db,'name');
+
+ _.each(sorted, item => {
+ if (!foundItems.includes(item.name)) {
+ foundItems.push(item.name);
+ item.body = LibFunctions.parseStr(item.body,dbReplacers);
+ if (!LibFunctions.setAbility( dbCS, item.name, item.body )) {
+ errFlag = true;
+ } else {
+ LibFunctions.setAttr( dbCS, [fields.CastingTimePrefix[0]+item.name, 'current'], item.ct );
+ LibFunctions.setAttr( dbCS, [fields.CastingTimePrefix[0]+item.name, 'max'], (spells ? item.cost : item.charge) );
+ LibFunctions.addMIspells( dbCS, item );
+ item.type.dbName().split('|').filter(t => !!t).map(t => {
+ let listType = typeList[t] ? typeList[t].type.toLowerCase() : (typeList.miscellaneous ? typeList.miscellaneous.type.toLowerCase() : undefined);
+ if (listType) {
+ if (!lists[listType]) lists[listType] = [];
+ if (!lists[listType].includes(item.name)) {
+ lists[listType].push(item.name);
+ }
+ } else {
+ LibFunctions.sendError('Unable to identify item type '+t+' when updating '+item.name+' in database '+dbFullName);
+ };
+ });
+ };
+ };
+ });
+ if (errFlag) {
+ LibFunctions.sendError( 'Unable to completely update database '+dbFullName );
+ } else {
+ _.each(typeList, dbList => dbList.field[0].length ? LibFunctions.setAttr( dbCS, [dbList.field[0],'current'], (lists[dbList.type.toLowerCase()] || ['']).join('|')) : '');
+ LibFunctions.setAttr( dbCS, fields.dbVersion, (dbObj.version || 1.0));
+ dbCS.set('avatar',(dbObj.avatar || ''));
+ dbCS.set('bio',(dbObj.bio || ''));
+ dbCS.set('controlledby',(dbObj.controlledby || 'All'));
+ dbCS.set('gmnotes',(dbObj.gmnotes || ''));
+ let msg = 'Updated database '+dbFullName+' to version '+String(dbObj.version);
+ if (!silent) LibFunctions.sendFeedback( msg, fields.feedbackName ); else log(msg);
+ }
+ }
+ return (errFlag);
+ }
+
+ /**
+ * Create an internal index of items in the databases
+ * to make searches much faster. Index entries indexed by
+ * database root name & short name (name in lower case with
+ * '-', '_' and ' ' ignored). index[0] = abilityID,
+ * index[1] = ct-attributeID
+ * v3.051 Check that other database-handling APIs have finished
+ * updating their databases and performed a handshake
+ **/
+
+ LibFunctions.updateDBindex = function() {
+ var rootDB, magicDB, validDB,
+ dbName, shortName, attrName, objList,
+ rootList = ['mu_spells_db','pr_spells_db','powers_db','mi_db','race_db','class_db','attacks_db','styles_db'],
+ index = [new Set()];
+
+ _.each( dbNames, (dbFields, dbName) => {
+ _.each( dbFields.db, (item, i) => {
+ rootDB = dbName.toLowerCase().match( /[a-z_]+?_db/i );
+ if (!item || !item.name) log('updateDBindex: item='+item.name+', i='+i+', unable to create shortName');
+ shortName = item.name.dbName();
+ if (_.isUndefined(index[rootDB])) index[rootDB] = {};
+ if (_.isUndefined(index[rootDB][shortName])) index[rootDB][shortName] = ['',String(item.ct),dbName,i];
+ });
+ });
+
+ objList = filterObjs( function(obj) {
+ if (obj.get('type') != 'ability') return false;
+ if (!(magicDB = getObj('character',obj.get('characterid')))) {
+// log('lib updateDBindex: found ability '+obj.get('name')+' not in any db');
+ return false;
+ }
+ dbName = magicDB.get('name').toLowerCase().replace(/-/g,'_');
+ if (/\s*v\d*\.\d*/.test(dbName)) {
+ return false;
+ }
+ let validDB = false;
+ for (const rDB of rootList) {
+ if (dbName.startsWith(rDB)) {
+ validDB = true;
+ rootDB = rDB;
+ break;
+ }
+ }
+ if (!validDB) {return false;}
+ let shortName = obj.get('name').dbName();
+
+ if (_.isUndefined(index[rootDB])) {index[rootDB] = {};}
+ if (_.isUndefined(index[rootDB][shortName]) || !index[rootDB][shortName][0].length || !stdDB.includes(dbName)) {
+ index[rootDB][shortName] = [obj.id,''];
+ }
+ return true;
+ });
+ objList = filterObjs( function(obj) {
+ if (obj.get('type') != 'attribute') {return false;}
+ attrName = obj.get('name');
+ if (!attrName || !attrName.toLowerCase().startsWith('ct-')) {return false;}
+ if (!(magicDB = getObj('character',obj.get('characterid')))) {
+ return false;
+ }
+ dbName = magicDB.get('name').toLowerCase().replace(/-/g,'_');
+ if (/\s*v\d*\.\d*/.test(dbName)) {return false;}
+ let validDB = false;
+ for (const rDB of rootList) {
+ if (dbName.startsWith(rDB)) {
+ validDB = true;
+ rootDB = rDB;
+ }
+ }
+ if (!validDB)
+ {return false;}
+ let shortName = attrName.dbName().substring(2);
+
+ if (!!!index[rootDB][shortName]) {
+ return false;
+ }
+ if (!stdDB.includes(dbName) || (!!!index[rootDB][shortName][1]) || (index[rootDB][shortName][1].length === 0)) {
+ index[rootDB][shortName][1] = obj.id;
+ };
+ return true;
+ });
+ magicList = {}; // Blank the internal index of items, as it might have changed and needs rebuilding
+ LibFunctions.sendFeedback( 'RPGMaster is now ready. ' );
+
+ return index;
+ }
+
+ /*
+ * Check a character sheet database and update/create the
+ * required attributes from the definitions. This should
+ * be run after updating or adding item or spell definitions.
+ */
+
+ LibFunctions.checkCSdb = function( dbFullName ) {
+
+ var dbName = dbFullName.toLowerCase(),
+ lists = {},
+ spellsDB,
+ dbCSlist,
+ dbTypeList;
+
+ var checkObj = function( obj ) {
+ var objCS, objCSname, objName, objBody, type, objCT, objChg, objCost, specs, spellsDB, classDB;
+
+ if (!obj || obj.get('type') !== 'ability') return false;
+ objCS = getObj('character',obj.get('characterid'));
+ if (!objCS) {log('checkObj: not found database object');return false;}
+ objCSname = objCS.get('name').toLowerCase();
+ if (dbName && dbName.length && (dbName !== '-db' && !objCSname.startsWith(dbName))) return false;
+ if (!objCSname.includes('-db') || (/\s*v\d*\.\d*/.test(objCSname))) return false;
+ objBody = obj.get('action');
+ spellsDB = objCSname.includes('spells') || objCSname.includes('powers');
+ classDB = objCSname.includes('class') || objCSname.includes('race');
+ specs = objBody.match(reSpecs);
+ objName = obj.get('name');
+ if (specs) {
+ dbTypeList = (spellsDB ? spTypeLists : (classDB ? clTypeLists : miTypeLists));
+ specs = specs ? [...('['+specs[0]+']').matchAll(reSpecClass)] : [];
+ for (const i of specs) {
+ type = i[1];
+ if (type && type.length) {
+ let typeList = type.dbName().split('|');
+ for (const t of typeList) {
+ let itemType = dbTypeList[t] ? dbTypeList[t].type : (dbTypeList.miscellaneous ? dbTypeList.miscellaneous.type : undefined);
+ if (itemType) {
+ if (!lists[objCS.id]) lists[objCS.id] = {};
+ if (!lists[objCS.id][itemType]) lists[objCS.id][itemType] = [];
+ if (!lists[objCS.id][itemType].includes(objName)) {
+ lists[objCS.id][itemType].push(objName);
+ };
+ } else if (_.isUndefined(itemType)) {
+ LibFunctions.sendError(objName+' is of undefined type '+t+'. Please correct this item definition.');
+ };
+ };
+ };
+ };
+ };
+ objCT = (objBody.match(reDataSpeed) || ['',0])[1];
+ objChg = (objBody.match(reDataCharge) || ['','uncharged'])[1];
+ objCost = (objBody.match(reDataCost) || ['',0])[1];
+ LibFunctions.setAttr( objCS, [fields.CastingTimePrefix[0]+objName, 'current'], objCT );
+ LibFunctions.setAttr( objCS, [fields.CastingTimePrefix[0]+objName, 'max'], (spellsDB ? objCost : objChg) );
+ LibFunctions.addMIspells( objCS, {name:objName,body:objBody} );
+ return true;
+ };
+
+ dbCSlist = filterObjs( obj => checkObj(obj) );
+ if (!dbCSlist || !dbCSlist.length) {
+ LibFunctions.sendFeedback('No databases found with a name that includes '+dbName,fields.feedbackName);
+ } else {
+ _.each(lists,(types,dbID) => {
+ let dbCS = getObj('character',dbID);
+ _.each(dbTypeList, dbList => {
+ if (types[dbList.type]) {
+ LibFunctions.setAttr( dbCS, [dbList.field[0],'current'], (types[dbList.type].sort().join('|') || '' ));
+ }
+ });
+ });
+ LibFunctions.sendFeedback(((!dbName || !dbName.length || dbName === '-db') ? 'All databases have' : ('Database '+dbFullName+' has')) + ' been updated',fields.feedbackName);
+ }
+ return;
+ }
+
+ /**
+ * Get a new DB index of all Ability Objects stored in
+ * database character sheets
+ **/
+
+ LibFunctions.getDBindex = function(forceUpdate = false) {
+ if (_.isUndefined(DBindex) || forceUpdate) {
+ DBindex = LibFunctions.updateDBindex();
+ }
+ return DBindex;
+ }
+
+ /**
+ * Update or create the help handouts
+ **/
+
+ LibFunctions.updateHandouts = function(handouts,silent,senderId) {
+
+ let classHelp = findObjs({ type:'handout', name:'Class Database Help' });
+ if (classHelp && classHelp[0]) classHelp[0].remove();
+ _.each(handouts,(obj,k) => {
+ let dbCS = findObjs({ type:'handout', name:obj.name },{caseInsensitive:true});
+ if (!dbCS || !dbCS[0]) {
+ log(obj.name+' not found. Creating version '+obj.version);
+ if (!silent) LibFunctions.sendFeedback(obj.name+' not found. Creating version '+obj.version);
+ dbCS = createObj('handout',{name:obj.name,inplayerjournals:(senderId || '')});
+ dbCS.set('notes',obj.bio);
+ dbCS.set('avatar',obj.avatar);
+ } else {
+ dbCS = dbCS[0];
+ dbCS.get('notes',function(note) {
+ let reVersion = new RegExp(obj.name+'\\s*?v(\\d+?.\\d*?)', 'im');
+ let version = note.match(reVersion);
+ version = (version && version.length) ? (parseFloat(version[1]) || 0) : 0;
+ if (version >= obj.version) {
+ if (!silent) LibFunctions.sendFeedback('Not updating handout '+obj.name+' as is already version '+obj.version);
+ return;
+ }
+ dbCS.set('notes',obj.bio);
+ dbCS.set('avatar',obj.avatar);
+ if (!silent) LibFunctions.sendFeedback(obj.name+' handout updated to version '+obj.version);
+ log(obj.name+' handout updated to version '+obj.version);
+ });
+ }
+ });
+ return;
+ }
+
+ /**
+ * Get the handout IDs for all handouts
+ **/
+
+ LibFunctions.getHandoutIDs = function() {
+
+ var handoutObjs = findObjs({ type: 'handout' }),
+ handoutIDs = {};
+ _.each( handoutObjs, h => {
+ let name = h.get('name').replace(/[-_&\s]/g,'');
+ handoutIDs[name] = h.id;
+ });
+ return handoutIDs;
+ };
+
+
+ /* -------------------------------- Utility Functions ---------------------------- */
+
+ /*
+ * Parse a data string for attribute settings
+ */
+
+ LibFunctions.parseData = function( attributes, reSpecs, def=true ) {
+
+ var parsedData = {},
+ val;
+
+ _.each( reSpecs, spec => {
+ val = attributes.match(spec.re);
+ if (!!val && val.length>1 && val[1].length) {
+ parsedData[spec.field] = val[1];
+ } else if (!def) {
+ parsedData[spec.field] = undefined;
+ } else {
+ parsedData[spec.field] = spec.def;
+ }
+ });
+ return parsedData;
+ }
+
+ /*
+ * Follow an inheritance chain of Class or Race database objects and
+ * consolidate their parsed data and attribute specifications
+ */
+
+ LibFunctions.resolveData = function( name, dBase, reThisData, defBase=true, doneList=[] ) {
+
+ var thisObj, thisSpecs, baseObj, thisData, thisAttr, parsedData,
+ baseData = [],
+ baseParsed = LibFunctions.parseData( '', reClassSpecs, defBase ),
+ baseAttr = LibFunctions.parseData( '', reAttr, defBase ),
+ debugging = false;
+
+ if (!name || !name.trim().length || doneList.includes(name.dbName())) {if (debugging) log('resolveData: no name or already processed '+name); return [baseParsed,baseAttr,baseData];}
+ thisObj = LibFunctions.abilityLookup( dBase, name, null, true );
+ if (!thisObj.obj) {if (debugging)log('resolveData: no definition of '+name+' in '+dBase);return [baseParsed,baseAttr,baseData];}
+ doneList.push(name.dbName());
+ thisSpecs = thisObj.specs();
+ if (!thisSpecs || !thisSpecs[0]) {if (debugging)log('resolveData: no Specs in definition of '+name);return [baseParsed,baseAttr,baseData];}
+ [baseParsed,baseAttr,baseData] = LibFunctions.resolveData( thisSpecs[0][4], dBase, reThisData, defBase, doneList );
+ thisData = thisObj.data(reThisData);
+ if (!thisData || !thisData[0]) {if (debugging)log('resolveData: no data in definition of '+name);return [baseParsed,baseAttr,baseData];}
+ parsedData = LibFunctions.parseData( thisData[0][0], reClassSpecs, false );
+ thisAttr = LibFunctions.parseData( parsedData.cattr+',', reAttr, false );
+ if (baseParsed) {
+ if (!parsedData.cattr) {
+ parsedData.cattr = baseParsed.cattr;
+ thisAttr = baseAttr;
+ } else if (baseAttr) {
+ thisAttr = _.mapObject(thisAttr, (attr,k) => attr == '-' ? '' : (!_.isUndefined(attr) ? attr : baseAttr[k]));
+ }
+ parsedData = _.mapObject(parsedData, (attr,k) => attr == '-' ? '' : (!_.isUndefined(attr) ? attr : baseParsed[k]));
+ }
+ if (debugging)log('resolveData: concatinating '+thisSpecs[0][4]+' baseData = '+baseData+'\nwith '+name+' thisData = '+thisData);
+ baseData.shift();
+ if (parsedData.numPowers && parsedData.numpowers[0]!=='=') thisData = thisData.concat(baseData);
+ if (debugging)log('resolveData: result is '+thisData.length+' long = '+thisData);
+ return [parsedData,thisAttr,thisData];
+ }
+
+ /*
+ * Function to replace special characters in a string
+ */
+
+ LibFunctions.parseStr=function(str,replaced=replacers){
+ return replaced.reduce((m, rep) => m.replace(rep[0], rep[1]), str);
+ }
+
+ /**
+ * Get valid character from a tokenID
+ */
+
+ LibFunctions.getCharacter = function( tokenID, silent=true ) {
+
+ var curToken,
+ charID,
+ charCS;
+
+ if (!tokenID) {
+ log('getCharacter: tokenID is invalid');
+ if (!silent) LibFunctions.sendError('Invalid RPGMaster arguments');
+ return undefined;
+ };
+
+ charCS = getObj( 'character', tokenID );
+ if (charCS) return charCS;
+
+ curToken = getObj( 'graphic', tokenID );
+
+ if (!curToken) {
+ log('getCharacter: tokenID is not a token');
+ if (!silent) LibFunctions.sendError('Invalid RPGMaster arguments');
+ return undefined;
+ };
+
+ charID = curToken.get('represents');
+
+ if (!charID) {
+ log('getCharacter: charID is invalid');
+ if (!silent) LibFunctions.sendError('Invalid RPGMaster arguments');
+ return undefined;
+ };
+
+ charCS = getObj('character',charID);
+
+ if (!charCS) {
+ log('getCharacter: charID is not for a character sheet');
+ if (!silent) LibFunctions.sendError('Invalid RPGMaster arguments');
+ return undefined;
+ };
+ return charCS;
+ };
+
+ /*
+ * Get Thac0 from the right place for this token. This should be from
+ * Bar2 current value on the token (to support multi-token monsters affected
+ * individually by +/- magic impacts on thac0) but checks if another bar allocated
+ * or, if none are, get from character sheet (monster or character)
+ */
+
+ LibFunctions.getTokenValue = function( curToken, tokenBar, field, altField, thac0_base ) {
+
+ var charCS = LibFunctions.getCharacter(curToken.id),
+ attr = field[0].toLowerCase(),
+ altAttr = altField ? altField[0].toLowerCase() : 'EMPTY',
+ property = field[1],
+ token_property = (property.toLowerCase() == 'current' ? 'value' : 'max'),
+ linkedToken = false,
+ barName, attrVal, attrObj, attrName, tokenField,
+ fieldIndex = state.RPGMaster.tokenFields.indexOf( field[0] );
+
+ if (!charCS) {return undefined;}
+
+ if (_.some( ['bar2_link','bar1_link','bar3_link'], linkName=>{
+ let linkID = curToken.get(linkName);
+ tokenField = linkName;
+ barName == '';
+ if (linkID && linkID.length) {
+ linkedToken = true;
+ attrObj = getObj('attribute',linkID);
+ if (attrObj) {
+ attrName = attrObj.get('name').toLowerCase();
+ barName = tokenField.substring(0,4);
+ return (attrName == attr) || (attrName == altAttr);
+ }
+ }
+ return false;
+ })) {
+ attrVal = curToken.get(barName+'_'+token_property);
+// attrObj.set(property,attrVal);
+ attrVal = !isNaN(attrVal) ? parseFloat(attrVal) : undefined;
+ }
+ if (isNaN(attrVal) && !linkedToken && fieldIndex >= 0) {
+ attrName = barName = 'bar'+(fieldIndex+1);
+ attrVal = parseFloat(curToken.get(barName+'_'+token_property));
+ }
+ if (isNaN(attrVal) && attr.includes('thac0')) {
+ if (!thac0_base) thac0_base = ['thac0-base','current','20'];
+ attrVal = parseFloat(LibFunctions.attrLookup( charCS, thac0_base ));
+ attrName = thac0_base[0];
+ barName = undefined;
+ }
+ if (isNaN(attrVal)) {
+ attrVal = parseFloat(LibFunctions.attrLookup( charCS, field ));
+ attrName = field[0];
+ barName = undefined;
+ }
+ if (isNaN(attrVal) && altField) {
+ attrVal = parseFloat(LibFunctions.attrLookup( charCS, altField ));
+ attrName = altField[0];
+ }
+ return {val:attrVal, name:(isNaN(attrVal) ? undefined : attrName), barName:(barName || attrName)};
+ }
+
+ /*
+ * Create an array of class objects for the classes
+ * of the specified character.
+ */
+
+ LibFunctions.classObjects = function( charCS ) {
+
+ var charLevels = ((_.filter( fields, (elem,l) => {return l.toLowerCase().includes('_level')}).filter( elem => 0 < (LibFunctions.attrLookup( charCS, elem ) || 0))) || fields.Fighter_level);
+ var charClass, baseClass, charLevel, dB = fields.ClassDB;
+
+ var classDef = _.filter( classLevels, a => {
+ return _.some( charLevels, b => {
+ return (a[1].includes(b[0]))
+ })
+ })
+ .map( elem => {
+ charClass = LibFunctions.attrLookup(charCS,elem[0]) || '';
+ charLevel = LibFunctions.attrLookup( charCS, elem[1] ) || 0;
+ if (elem[0][0] == fields.Wizard_class[0]) {
+ baseClass = 'wizard';
+ } else if (elem[0][0] == fields.Priest_class[0]) {
+ baseClass = 'priest';
+ } else if (elem[0][0] == fields.Rogue_class[0]) {
+ baseClass = 'rogue';
+ } else if (elem[0][0] == fields.Psion_class[0]) {
+ baseClass = 'psion';
+ } else if (elem[1][0] == fields.Monster_hitDice[0]) {
+ let monsterHD = parseInt(LibFunctions.attrLookup( charCS, fields.Monster_hitDice )) || 0,
+ monsterHPplus = parseInt(LibFunctions.attrLookup( charCS, fields.Monster_hpExtra )) || 0,
+ monsterIntField = LibFunctions.attrLookup( charCS, fields.Monster_int ) || '',
+ monsterIntNum = parseInt((monsterIntField.match(/\d+/)||["1"])[0]) || 0,
+ monsterInt = monsterIntField.toLowerCase().includes('non') ? 0 : monsterIntNum;
+ charLevel = Math.ceil((monsterHD + Math.ceil(monsterHPplus/4)) / (monsterInt != 0 ? 1 : 2)); // Calculation based on p65 of DMG
+ baseClass = 'creature';
+ if (!charClass || !charClass.length) {
+ charClass = LibFunctions.attrLookup(charCS,fields.Race);
+ dB = fields.RaceDB;
+ };
+ if (!charClass || !charClass.length) {
+ charClass = 'creature';
+ dB = fields.ClassDB;
+ };
+
+ } else {
+ baseClass = 'warrior';
+ }
+ let classObj = LibFunctions.abilityLookup( dB, charClass, charCS, true );
+ if (!charClass.length || !classObj.obj) {
+ charClass = baseClass;
+ classObj = LibFunctions.abilityLookup( dB, baseClass, charCS );
+ }
+ return {name:charClass.dbName(), dB:classObj.dB, base:baseClass.dbName(), dBbase:fields.ClassDB, level:charLevel, obj:classObj.obj};
+ });
+ if (_.isUndefined(classDef) || !classDef.length) classDef = [{name:'creature', base:'warrior', level:0, obj:LibFunctions.abilityLookup( fields.ClassDB, 'creature', charCS ).obj}];
+ classDef = classDef.map(c => {[c.classData] = LibFunctions.resolveData(charClass, dB, reData);return c});
+ return classDef;
+ };
+
+ /*
+ * Determine if a particular item type or superType is an
+ * allowed type for a specific class.
+ */
+
+ LibFunctions.classAllowedItem = function( charCS, wname, wt, wst, allowedItemsByClass ) {
+
+ wt = wt ? wt.dbName() : '-';
+ wst = wst ? wst.dbName() : '-';
+ wname = wname ? wname.dbName() : '-';
+ allowedItemsByClass = allowedItemsByClass.dbName();
+
+ var typeDefaults = {weaps:'any',ac:'any',sps:'any',spm:'',spb:'',align:'any',race:'any'},
+ itemType = !_.isUndefined(typeDefaults[allowedItemsByClass]) ? allowedItemsByClass : 'weaps',
+ forceFalse = false;
+
+ var classAllowed = LibFunctions.classObjects( charCS ).some( elem => {
+ if ([wt,wst].includes('innate')) return true;
+
+ if (!elem.obj) return false;
+ let allowedItems = (elem.classData[itemType] || typeDefaults[itemType]).toLowerCase().replace(reIgnore,'').split('|');
+ return allowedItems.reduce((p,c) => {
+ let item = '!+'.includes(c[0]) ? c.slice(1) : c,
+ found = item.includes('any') || (wt.includes(item) || wst.includes(item) || (wt=='-' && wst=='-' && wname.includes(item)));
+ forceFalse = (forceFalse || (c[0] === '!' && found)) && !(c[0] === '+' && found);
+ return (p || found) && !forceFalse;
+ }, false);
+ }),
+ raceObj = LibFunctions.abilityLookup( fields.RaceDB, (LibFunctions.attrLookup( charCS, fields.Race ) || 'human') ),
+ raceAllowed = true;
+
+ forceFalse = false;
+ if (raceObj.obj) {
+ let allowedItems = LibFunctions.parseData((raceObj.data(/}}\s*?(?:Class|Race)Data\s*?=.*?{{/im)[0][0] || ''),reClassSpecs)[itemType];
+ raceObj = LibFunctions.abilityLookup( fields.RaceDB, (raceObj.specs()[0] || [])[4], charCS, true );
+ if (raceObj.obj) {
+ allowedItems += (allowedItems && allowedItems.length ? '|' : '')+LibFunctions.parseData((raceObj.data(/}}\s*?(?:Class|Race)Data\s*?=(.*?){{/im)[0][0] || ''),reClassSpecs)[itemType];
+ }
+ if (!allowedItems || !allowedItems.length) {
+ allowedItems = typeDefaults[itemType];
+ }
+ allowedItems = allowedItems.dbName().split('|');
+ raceAllowed = allowedItems.reduce((p,c) => {
+ let item = '!+'.includes(c[0]) ? c.slice(1) : c,
+ found = item.includes('any') || (wt.includes(item) || wst.includes(item) || (wt=='-' && wst=='-' && wname.includes(item)));
+ forceFalse = (forceFalse || (c[0] === '!' && found)) && !(c[0] === '+' && found);
+ return (p || found) && !forceFalse;
+ }, false);
+ };
+ return (classAllowed && raceAllowed);
+ };
+
+ /*
+ * For magic items that have stored spells or powers, extract
+ * these from the MI definition and create or update the
+ * related character sheet database attribute.
+ */
+
+ LibFunctions.addMIspells = function( dbCS, dbItem ) {
+
+ const reSpellSpecs = Object.freeze ({
+ name: {field:'name',def:'-',re:/[\[,\s]w:([\s\w\-\+]+?)[,\]]/i},
+ type: {field:'spell',def:'',re:/[\[,\s]cl:(PR|MU|PW)[,\s\]]/i},
+ speed: {field:'speed',def:0,re:/[\[,\s]sp:([d\d\+\-]+?)[,\s\]]/i},
+ level: {field:'level',def:1,re:/[\[,\s]lv:(\d+?)[,\s\]]/i},
+ perDay: {field:'perDay',def:1,re:/[\[,\s]pd:([-+]?\d+?)[,\s\]]/i},
+ cost: {field:'cost',def:0,re:/[\[,\s]gp:([-+]?\d+?\.?\d*?)[,\s\]]/i},
+ recharge: {field:'type',def:'uncharged',re:/[\[,\s]rc:([\-\w]+?)[,\s\]]/i},
+ spheres: {field:'sph',def:'',re:/[\[,\s]sph:([\s\w\-\|\d]+?)[,\]]/i},
+ });
+
+ var itemData = dbItem.body.match(/}}[\s\w\-]*?(? {
+ let parsedData = LibFunctions.parseData( spell[0], reSpellSpecs );
+ if (parsedData && parsedData.spell && ['MU','PR','PW'].includes(parsedData.spell.toUpperCase())) {
+ let spellType = parsedData.spell.toUpperCase();
+ spellSet[spellType][0].push(parsedData.name);
+ spellSet[spellType][1].push((spellType == 'PW') ? (parsedData.perDay+'.'+parsedData.perDay) : (parsedData.level+'.0'));
+ }
+ });
+// if (spellSet.PW[0].length || LibFunctions.attrLookup( dbCS, [fields.ItemPowersList[0]+dbItem.name,fields.ItemPowersList[1]], null, -1, 0, false, false )) {
+ if (spellSet.PW[0].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemPowersList[0]+dbItem.name,fields.ItemPowersList[1]], spellSet.PW[0].join() );
+ if (spellSet.PW[1].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemPowerValues[0]+dbItem.name,fields.ItemPowerValues[1]], spellSet.PW[1].join() );
+ }
+ }
+// if (spellSet.PR[0].length || LibFunctions.attrLookup( dbCS, [fields.ItemPRspellsList[0]+dbItem.name,fields.ItemPRspellsList[1]], null, -1, 0, false, false )) {
+ if (spellSet.PR[0].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemPRspellsList[0]+dbItem.name,fields.ItemPRspellsList[1]], spellSet.PR[0].join() );
+ if (spellSet.PR[1].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemPRspellValues[0]+dbItem.name,fields.ItemPRspellValues[1]], spellSet.PR[1].join() );
+ }
+ }
+// if (spellSet.MU[0].length || LibFunctions.attrLookup( dbCS, [fields.ItemMUspellsList[0]+dbItem.name,fields.ItemMUspellsList[1]], null, -1, 0, false, false )) {
+ if (spellSet.MU[0].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemMUspellsList[0]+dbItem.name,fields.ItemMUspellsList[1]], spellSet.MU[0].join() );
+ if (spellSet.MU[1].length) {
+ LibFunctions.setAttr( dbCS, [fields.ItemMUspellValues[0]+dbItem.name,fields.ItemMUspellValues[1]], spellSet.MU[1].join() );
+ }
+ }
+ return spellSet;
+ }
+
+ /**
+ * String together the value of the specified item type from
+ * all databases with the specified root name, separated
+ * by |. This is used to get a complete list of available
+ * magic spell or item macros across all databases of a
+ * specific type.
+ **/
+
+ LibFunctions.getMagicList = function( rootDB, mapObj, objType, defList='', other=false, otherMsg='Specify', alphabet=false ) {
+
+ objType = _.isArray(objType) ? objType.join().toLowerCase() : objType.toLowerCase();
+ if (!magicList[rootDB] || !magicList[rootDB][objType] || magicList[rootDB][objType].alpha != alphabet) {
+
+ let list = [],
+ rDB = rootDB.toLowerCase().replace(/-/g,'_'),
+ typeList;
+
+ if (_.isUndefined(DBindex[rDB])) {
+ for (const dBname of _.keys(DBindex)) {
+ if (rDB.startsWith(dBname)) {
+ rDB = dBname;
+ break;
+ }
+ }
+ }
+ _.each( DBindex[rDB], (objIndex,objName) => {
+ if (objIndex[0].length) {
+ let obj = getObj('ability',objIndex[0]);
+ let objDef = obj.get('action');
+ let specs = objDef.match(reSpecs);
+ specs = specs ? [...('['+specs[0]+']').matchAll(reSpecsAll)] : [];
+
+ outer_block: {
+ for (const s of specs) {
+ typeList = s[2].dbName().split('|');
+ for (const t of typeList) {
+ if (t==='magic') continue;
+ if ((mapObj[t] && !!mapObj[t].type && objType.includes(mapObj[t].type))
+ || (!mapObj[t] && mapObj.miscellaneous && objType.includes(mapObj.miscellaneous.type))) {
+ list.push(obj.get('name').dispName());
+ break outer_block;
+ }
+ }
+ }
+ }
+ } else {
+ typeList = dbNames[objIndex[2]].db[objIndex[3]].type.dbName().split('|');
+
+ for (const t of typeList) {
+ if (t === 'magic') continue;
+ if ((mapObj[t] && !!mapObj[t].type && objType.includes(mapObj[t].type))
+ || (!mapObj[t] && mapObj.miscellaneous && objType.includes(mapObj.miscellaneous.type))) {
+ list.push(dbNames[objIndex[2]].db[objIndex[3]].name.dispName());
+ break;
+ }
+ }
+ }
+ });
+
+ if (!list.length || !list[0].length) {
+ list = defList.split('|');
+ }
+ list = _.uniq(list.filter( list => !!list ).sort());
+
+ if (alphabet) {
+ let alphaList = [];
+ for (let i=65; i<=90; i++) {
+ let subList = list.filter( n => n.toUpperCase().charCodeAt(0)==i )
+ .concat(list.filter( n => n.toUpperCase().startsWith('POTION OF ') && n.charCodeAt(10)==i ),
+ list.filter( n => n.toUpperCase().startsWith('RING OF ') && n.charCodeAt(8)==i ),
+ list.filter( n => n.toUpperCase().startsWith('SCROLL OF ') && n.charCodeAt(10)==i ))
+ .join('|');
+ if (subList && subList.length) {
+ alphaList.push(String.fromCharCode(i)+',?{Choose from |'+subList+'}');
+ }
+ };
+ list = alphaList;
+ }
+ if (other) {
+ if (!alphabet) list = list.map( e => e + ',' + e );
+ list.push('Other,?{'+otherMsg+'}');
+ }
+
+ if (!magicList[rootDB]) magicList[rootDB] = {};
+ if (!magicList[rootDB][objType]) magicList[rootDB][objType] = {};
+ magicList[rootDB][objType].list = list.join('|');
+ magicList[rootDB][objType].alpha = alphabet;
+ }
+ return magicList[rootDB][objType].list;
+ }
+
+ /**
+ * Get the displayable type of an item, derived from the
+ * item's database "Specs" field, for display in search-able
+ * containers
+ **/
+
+ LibFunctions.getShownType = function( miObj ) {
+ var specs = miObj.specs(),
+ mi, miType;
+ if (specs) {
+ let miClasses = specs.reduce((a,b) => a.concat([b[2]]), []).join('|');
+ let lowerMI = miClasses.toLowerCase();
+
+ mi = miClasses.split('|').find(itemClass => _.isUndefined(miTypeLists[itemClass.dbName()]) || !(['weapon','ammo','armour','armor'].includes(miTypeLists[itemClass.dbName()].type)));
+ if (!mi) {
+ mi = miClasses.split('|').find(itemClass => ['weapon','ammo','armour','armor'].includes(miTypeLists[itemClass.dbName()].type));
+ }
+ miType = miTypeLists[mi.dbName()] ? miTypeLists[mi.dbName()].type : 'miscellaneous';
+
+ switch (miType) {
+ case 'weapon':
+ case 'ammo':
+ mi = (specs.find(itemSpecs => itemSpecs[2].toLowerCase().includes(mi.toLowerCase())) || ['','','','','mi'])[4];
+ break;
+ case 'armour':
+ case 'armor':
+ mi = (specs.find(itemSpecs => itemSpecs[2].toLowerCase().includes(mi.toLowerCase())) || ['','mi'])[1];
+ break;
+ case 'miscellaneous':
+ let data = miObj.data(/}}[\s\w\-]*?(? itemSpecs[2].toLowerCase().includes(mi.toLowerCase())) || ['','','','','mi'])[4];
+ }
+ break;
+ }
+ }
+ return mi.replace(/[-_]/g,' ').replace(/\|/g,'/');
+ };
+
+ /**
+ * Find an item identified as a Power, but which might actually
+ * be in a different database, as powers can be anything magical
+ **/
+
+ LibFunctions.findPower = function( charCS, power, silent=false, def=true ) {
+
+ if (!power || !power.length) return LibFunctions.abilityLookup( fields.PowersDB, '', charCS, true, false );
+
+ const dbList = [['PW-',fields.PowersDB],['MU-',fields.MU_SpellsDB],['PR-',fields.PR_SpellsDB],['MI-',fields.MagicItemDB]];
+
+ var powerType = power.substring(0,3),
+ powerLib;
+
+ if (_.some(dbList,dB=>dB[0]===powerType.toUpperCase())) power = power.slice(powerType.length);
+
+ if (!_.some(dbList, dB => {
+ if (powerType.toUpperCase() === dB[0]) {
+ powerLib = LibFunctions.abilityLookup( dB[1], power, null, true, def );
+ return true;
+ } else {
+ return false;
+ }
+ })) {
+ _.some(dbList, dB => {
+ powerLib = LibFunctions.abilityLookup( dB[1], power, null, true, false );
+ return !_.isUndefined(powerLib.obj);
+ });
+ };
+ if (!powerLib.obj) {
+ powerLib = LibFunctions.abilityLookup( fields.PowersDB, power, charCS, silent, def );
+ }
+ powerLib.name = power;
+ return powerLib;
+ }
+
+ /**
+ * Find and return total level of a character
+ **/
+
+ LibFunctions.characterLevel = function( charCS ) {
+ var level = parseInt((LibFunctions.attrLookup( charCS, fields.Total_level ) || 0),10);
+ if (!level) {
+ level = parseInt((LibFunctions.attrLookup( charCS, fields.Fighter_level ) || 0),10)
+ + parseInt((LibFunctions.attrLookup( charCS, fields.Wizard_level ) || 0),10)
+ + parseInt((LibFunctions.attrLookup( charCS, fields.Priest_level ) || 0),10)
+ + parseInt((LibFunctions.attrLookup( charCS, fields.Rogue_level ) || 0),10)
+ + parseInt((LibFunctions.attrLookup( charCS, fields.Psion_level ) || 0),10)
+ + (parseInt((LibFunctions.attrLookup( charCS, fields.Monster_hitDice ) || 0),10)
+ + ((parseInt((LibFunctions.attrLookup( charCS, fields.Monster_hpExtra ) || 0),10) >= 3) ? 1 : 0));
+ }
+ return level;
+ }
+
+ /*
+ * Find and return the level for spell casting.
+ * MU: Wizard_level
+ * PR: Priest_level
+ * POWER or MI: all levels added
+ */
+
+ LibFunctions.caster = function( charCS, casterType ) {
+
+ var level=0, castingLevel=0, charClass, castingClass;
+
+ if (casterType == 'MI' || casterType == 'POWER' || casterType == 'PW') {
+ level = LibFunctions.characterLevel( charCS );
+ return {lv:level,cl:'',clv:level,ccl:''};
+ }
+
+ for (const casterData of casterLevels) {
+ charClass = (LibFunctions.attrLookup( charCS, casterData[0] ) || '');
+ castingClass = charClass.toUpperCase().replace(reIgnore,'');
+ level = LibFunctions.attrLookup(charCS,casterData[1]) || 0;
+ if (level > 0 && (_.isUndefined(spellsPerLevel[castingClass]) || _.isUndefined(spellsPerLevel[castingClass][casterType]))) {
+ if (casterType == 'MU' && casterData[0][0] == fields.Wizard_class[0]) {
+ castingClass = 'WIZARD';
+ } else if (casterType == 'PR' && casterData[0][0] == fields.Priest_class[0]) {
+ castingClass ='PRIEST';
+ } else {
+ level = 0;
+ }
+ }
+ if (level > 0) break;
+ }
+ if (level>0 && castingClass) {
+ castingLevel = Math.min(Math.max((1+parseInt(level) - spellsPerLevel[castingClass][casterType][0][1]),0),spellsPerLevel[castingClass][casterType][0][2]);
+ if (castingLevel <= 0) castingLevel = -1;
+ };
+ return {lv:level,cl:charClass,clv:castingLevel,ccl:castingClass};
+ };
+
+ /* ---------------------------- Game Rule-Specific Functions -------------------------------- */
+
+ /*
+ * Return the base Thac0 of a character based on class & level
+ */
+
+ LibFunctions.handleGetBaseThac0 = function( charCS ) {
+
+ return Math.min( LibFunctions.attrLookup( charCS, fields.MonsterThac0 ) || 20,
+ baseThac0table[0][LibFunctions.attrLookup( charCS, fields.Fighter_level ) || 0],
+ baseThac0table[1][LibFunctions.attrLookup( charCS, fields.Wizard_level ) || 0],
+ baseThac0table[2][LibFunctions.attrLookup( charCS, fields.Priest_level ) || 0],
+ baseThac0table[3][LibFunctions.attrLookup( charCS, fields.Rogue_level ) || 0],
+ baseThac0table[4][LibFunctions.attrLookup( charCS, fields.Psion_level ) || 0]
+ );
+ }
+
+ /*
+ * Scan Race, Class, Level and MI data to set the saving throws table
+ * for a particular Token
+ */
+
+ LibFunctions.handleCheckSaves = function( args, senderId, selected, silent=false ) {
+
+ const blankMods = {par:0,poi:0,dea:0,rod:0,sta:0,wan:0,pet:0,pol:0,bre:0,spe:0,str:0,con:0,dex:0,int:0,wis:0,chr:0},
+ xlate = {att:'Attribute',par:'Paralysis',poi:'Poison',dea:'Death',rod:'Rod',sta:'Staff',wan:'Wand',pet:'Petrify',pol:'Polymorph',bre:'Breath',spe:'Spell',str:'Strength',con:'Constitution',dex:'Dexterity',int:'Intelligence',wis:'Wisdom',chr:'Charisma'},
+ reSave = /[,\[\s]sv([a-z]{3}):([-\+]?\d+)[,\s\]]/g;
+
+ var tokenID,
+ charCS,
+ attkMenu,
+ content = '&{template:'+fields.defaultTemplate+'}';
+
+ if (attkMenu = (args && args[0])) {
+ selected = [];
+ selected.push(getObj('graphic',args[0]));
+ }
+ _.each( selected, curToken => {
+
+ tokenID = attkMenu ? curToken.id : curToken._id;
+ charCS = LibFunctions.getCharacter( tokenID, true );
+
+ if (!charCS) {
+ return;
+ }
+ let tokenName = getObj('graphic',tokenID).get('name'),
+ classes = LibFunctions.classObjects( charCS ),
+ race = (LibFunctions.attrLookup( charCS, fields.Race ) || 'human').dbName(),
+ ItemNames = LibFunctions.getTableField( charCS, {}, fields.Items_table, fields.Items_name ),
+ saves = [],
+ classSaves, classMods,
+ mods = _.isUndefined(raceSaveMods[race]) ? (_.find(raceSaveMods, (m,k) => race.includes(k)) || raceSaveMods.human) : raceSaveMods[race],
+ raceBonus = _.isUndefined(classSaveMods[race]) ? (_.find(classSaveMods, (m,k) => race.includes(k)) || blankMods) : classSaveMods[race],
+ setFlags = {att:false,par:false,poi:false,dea:false,rod:false,sta:false,wan:false,pet:false,pol:false,bre:false,spe:false,str:false,con:false,dex:false,int:false,wis:false,chr:false},
+ miMods = [],
+ attribute, attrVal, item,
+ itemText = '';
+
+// log('handleCheckSaves: after initialisation, mods = '+_.chain(mods).pairs().flatten().value().join(','));
+
+ content += (selected.length == 1) ? '{{name='+tokenName+'\'s Saving Throws}}' : '{{name=Setting Saving Throws}}';
+
+ classes.forEach( c => {
+ if (!saveLevels[c.name]) {
+ classSaves = baseSaves[c.base][saveLevels[c.base][Math.min(c.level,saveLevels[c.base].length)]];
+ } else {
+ classSaves = baseSaves[c.name][saveLevels[c.name][Math.min(c.level,saveLevels[c.name].length)]];
+ }
+ if (!saves || !saves.length) {
+ saves = classSaves;
+ } else {
+ saves = saves.map((v,k)=> Math.min(v,classSaves[k]));
+ }
+ itemText += '{{'+c.obj[1].name+'=Level '+c.level+'='+classSaves+'}}';
+ });
+ switch (mods.att) {
+ case 'str':
+ attribute = fields.Strength;
+ break;
+ case 'dex':
+ attribute = fields.Dexterity;
+ break;
+ case 'con':
+ attribute = fields.Constitution;
+ break;
+ case 'int':
+ attribute = fields.Intelligence;
+ break;
+ case 'wis':
+ attribute = fields.Wisdom;
+ break;
+ case 'chr':
+ attribute = fields.Charisma;
+ break;
+ default:
+ attribute = undefined;
+ };
+ if (attribute) {
+ attrVal = parseInt(LibFunctions.attrLookup( charCS, attribute )) || -1;
+ } else {
+ attrVal = -1;
+ }
+ if (_.some(mods,(m,k)=>!!m && k!='att')) itemText += '{{'+LibFunctions.attrLookup( charCS, fields.Race )+'=';
+ mods = _.mapObject(mods,(v,k) => {
+ if (k == 'att') {
+ return v;
+ } else {
+ if (v != 0) itemText += xlate[k]+':'+(Math.floor(attrVal != -1 ? (attrVal/v) : v)+raceBonus[k])+', ';
+ return Math.floor(v != 0 ? (attrVal != -1 ? (attrVal/v) : v) : 0)+raceBonus[k];
+ }
+ });
+ if (_.some(mods,(m,k)=>!!m && k!='att')) itemText += '}}';
+
+// log('handleCheckSaves: after race saves, mods = '+_.chain(mods).pairs().flatten().value().join(','));
+
+ classes.forEach( c => {
+ classMods = classSaveMods[c.name] || classSaveMods[c.base] || classSaveMods.undefined;
+ if (!mods && !mods.length) {
+ mods = classMods;
+ } else {
+ mods = _.mapObject(mods,(v,k)=>{return k != 'att' ? v+classMods[k] : v});
+ }
+ if (classMods.att) classMods.att = classMods.par;
+ if (_.some(classMods)) itemText += '{{'+c.name+' Mods=';
+ let vals = _.chain(classMods).values().uniq().value();
+ if (vals.length == 1) {
+ itemText += 'All mods:'+vals[0];
+ } else {
+ _.mapObject(classMods,(v,k)=> ((k!='att' && v) ? (itemText += xlate[k]+':'+v+' ') : ''));
+ }
+ if (_.some(classMods)) itemText += '}}';
+ });
+
+// log('handleCheckSaves: after class saves, mods = '+_.chain(mods).pairs().flatten().value().join(','));
+
+ for (let itemRow = 0; !_.isUndefined(item = ItemNames.tableLookup( fields.Items_name, itemRow, false )); itemRow++) {
+ if (item != '-') {
+ let trueItem = ItemNames.tableLookup( fields.Items_trueName, itemRow );
+ let itemObj = LibFunctions.abilityLookup( fields.MagicItemDB, trueItem, charCS );
+ if (itemObj.obj) {
+ itemObj.obj[1].body = itemObj.obj[1].body.toLowerCase();
+ let specsArray = itemObj.specs(/}}\s*specs=\s*?(.*?)\s*?{{/im); // specs ? [...('['+specs[0]+']').matchAll(/\[\s*?(\w[\s\|\w\-]*?)\s*?,\s*?(\w[\s\|\w\-]*?\w)\s*?,\s*?(\w[\s\w]*?\w)\s*?,\s*?(\w[\s\|\w\-]*?\w)\s*?\]/g)] : undefined;
+ let miClass = specsArray ? (specsArray[0][2].dbName() || 'magicitem') : 'magicitem',
+ dataArray = itemObj.data(/}}\s*\w*?data\s*=.*?sv[a-z]{3}:.*?{{/g); // [...itemDef.matchAll(/}}\s*\w*?data\s*=.*?sv[a-z]{3}:.*?{{/g)];
+
+ if (miClass.includes('ring') && miClass.includes('protection')) {
+ let leftRing = LibFunctions.attrLookup( charCS, fields.Equip_leftTrueRing ) || '-',
+ rightRing = LibFunctions.attrLookup( charCS, fields.Equip_rightTrueRing ) || '-';
+ if (![leftRing,rightRing].includes(trueItem)) {
+ itemText += '{{'+item+'=Is not currently worn}}';
+ continue;
+ }
+ }
+ let addedText = '';
+ _.each( dataArray, data => {
+ if (!data) return;
+ let saveMods = data ? [...data[0].matchAll(reSave)] : [];
+ _.each( saveMods, m => {
+ addedText = '{{'+item+'=';
+ if (!miMods[miClass]) miMods[miClass] = blankMods;
+ if (m[1] == 'all') {
+ addedText += 'All mods: '+m[2];
+ miMods[miClass] = _.mapObject(miMods[miClass], (v,k)=> {
+ if (k != 'att') {
+ if ('+-'.includes(m[2][0]) && !setFlags[m[1]]) {
+ return (v+(parseInt(m[2]) || 0));
+ } else if (m[2][0] == '=') {
+ if (setFlags[m[1]]) {
+ return Math.max(v,(parseInt(m[2]) || 0));
+ } else {
+ setFlags[m[1]] = true;
+ return (parseInt(m[2].substring(1)) || 0);
+ }
+ } else if (!setFlags[m[1]]) {
+ return Math.max(v,(parseInt(m[2]) || 0));
+ }
+ } else {
+ return v;
+ }
+ });
+ } else if (mods[m[1]]) {
+ if (m[1] != 'att') {
+ addedText += xlate[m[1]]+': '+m[2]+', ';
+ if ('+-'.includes(m[2][0]) && !setFlags[m[1]]) {
+ miMods[miClass][m[1]] += (parseInt(m[2]) || 0);
+ } else if (m[2][0] == '=') {
+ if (setFlags[m[1]]) {
+ miMods[miClass][m[1]] = Math.max(v,(parseInt(m[2]) || 0));
+ } else {
+ setFlags[m[1]] = true;
+ miMods[miClass][m[1]] = (parseInt(m[2].substring(1)) || 0);
+ }
+ } else if (!setFlags[m[1]]) {
+ miMods[miClass][m[1]] = Math.max(v,(parseInt(m[2]) || 0));
+ }
+ } else {
+ miMods[miClass][m[1]] = v;
+ }
+ };
+ addedText += '}}';
+ });
+ });
+ itemText += addedText;
+ };
+ };
+ };
+// log('handleCheckSaves: after mi check, mods = '+_.chain(mods).pairs().flatten().value().join(','));
+
+ _.mapObject(miMods, function(s,c) {
+ mods = _.mapObject(mods, function(v,k) {
+ return (setFlags[k] ? s[k] : (v + s[k]));
+ });
+ });
+
+// log('handleCheckSaves: after mi saves, mods = '+_.chain(mods).pairs().flatten().value().join(','));
+
+ LibFunctions.setAttr( charCS, fields.Saves_monParalysis, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_monPoison, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_monDeath, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_monRod, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_monStaff, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_monWand, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_monPetri, saves[2] );
+ LibFunctions.setAttr( charCS, fields.Saves_monPolymorph, saves[2] );
+ LibFunctions.setAttr( charCS, fields.Saves_monBreath, saves[3] );
+ LibFunctions.setAttr( charCS, fields.Saves_monSpell, saves[4] );
+ LibFunctions.setAttr( charCS, fields.Saves_paralysis, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_poison, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_death, saves[0] );
+ LibFunctions.setAttr( charCS, fields.Saves_rod, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_staff, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_wand, saves[1] );
+ LibFunctions.setAttr( charCS, fields.Saves_petrification, saves[2] );
+ LibFunctions.setAttr( charCS, fields.Saves_polymorph, saves[2] );
+ LibFunctions.setAttr( charCS, fields.Saves_breath, saves[3] );
+ LibFunctions.setAttr( charCS, fields.Saves_spell, saves[4] );
+ LibFunctions.setAttr( charCS, fields.Saves_modParalysis, mods.par );
+ LibFunctions.setAttr( charCS, fields.Saves_modPoison, mods.poi );
+ LibFunctions.setAttr( charCS, fields.Saves_modDeath, mods.dea );
+ LibFunctions.setAttr( charCS, fields.Saves_modRod, mods.rod );
+ LibFunctions.setAttr( charCS, fields.Saves_modStaff, mods.sta );
+ LibFunctions.setAttr( charCS, fields.Saves_modWand, mods.wan );
+ LibFunctions.setAttr( charCS, fields.Saves_modPetrification, mods.pet );
+ LibFunctions.setAttr( charCS, fields.Saves_modPolymorph, mods.pol );
+ LibFunctions.setAttr( charCS, fields.Saves_modBreath, mods.bre );
+ LibFunctions.setAttr( charCS, fields.Saves_modSpell, mods.spe );
+ LibFunctions.setAttr( charCS, fields.Saves_modStrength, mods.str );
+ LibFunctions.setAttr( charCS, fields.Saves_modConstitution, mods.con );
+ LibFunctions.setAttr( charCS, fields.Saves_modDexterity, mods.dex );
+ LibFunctions.setAttr( charCS, fields.Saves_modIntelligence, mods.int );
+ LibFunctions.setAttr( charCS, fields.Saves_modWisdom, mods.wis );
+ LibFunctions.setAttr( charCS, fields.Saves_modCharisma, mods.chr );
+
+ content +='{{Saves='
+ + '**'+saves[0]+'** | Paralysis('+(mods.par>=0?'+':'')+mods.par+'), Poison('+(mods.poi>=0?'+':'')+mods.poi+'), Death('+(mods.dea>=0?'+':'')+mods.dea+') | '
+ + '**'+saves[1]+'** | Rod('+(mods.rod>=0?'+':'')+mods.rod+'), Staff('+(mods.sta>=0?'+':'')+mods.sta+'), Wand('+(mods.wan>=0?'+':'')+mods.wan+') | '
+ + '**'+saves[2]+'** | Petrification('+(mods.pet>=0?'+':'')+mods.pet+'), Polymorph('+(mods.pol>=0?'+':'')+mods.pol+') | '
+ + '**'+saves[3]+'** | Breath('+(mods.bre>=0?'+':'')+mods.bre+') | '
+ + '**'+saves[4]+'** | Spell('+(mods.spe>=0?'+':'')+mods.spe+') | '
+ + ' }}'
+ + '{{Attribute Checks='
+ + '**'+LibFunctions.attrLookup(charCS,fields.Strength)+'** | Strength('+(mods.str>=0?'+':'')+mods.str+') | '
+ + '**'+LibFunctions.attrLookup(charCS,fields.Constitution)+'** | Constitution('+(mods.con>=0?'+':'')+mods.con+') | '
+ + '**'+LibFunctions.attrLookup(charCS,fields.Dexterity)+'** | Dexterity('+(mods.dex>=0?'+':'')+mods.dex+') | '
+ + '**'+LibFunctions.attrLookup(charCS,fields.Intelligence)+'** | Intelligence('+(mods.int>=0?'+':'')+mods.int+') | '
+ + '**'+LibFunctions.attrLookup(charCS,fields.Wisdom)+'** | Wisdom('+(mods.wis>=0?'+':'')+mods.wis+') | '
+ + '**'+LibFunctions.attrLookup(charCS,fields.Charisma)+'** | Charisma('+(mods.chr>=0?'+':'')+mods.chr+') | '
+ + ' }}'
+ + ((selected.length == 1) ? itemText : '');
+
+ });
+ if (attkMenu || (args && args[1])) {
+ content += '{{desc=[Return to Menu]('+(attkMenu ? ('!attk --button SAVES|'+tokenID) : ('!cmd --button '+args[1]))+')}}';
+ }
+ if (!silent) LibFunctions.sendResponse( charCS, content, senderId, null, null, tokenID );
+ return;
+ }
+
+ /*
+ * Reload all weapons in the InHand tables, to set correct
+ * data after a race, class or level change. Will not work
+ * for weapons entered manually into the weapon tables
+ */
+
+ LibFunctions.handleCheckWeapons = function( tokenID, charCS ) {
+
+ var InHand = LibFunctions.getTable( charCS, fieldGroups.INHAND ),
+ itemIndex = InHand.tableLookup( fields.InHand_index, 0 );
+ if (itemIndex.length && !isNaN(itemIndex)) {
+ LibFunctions.sendAPI('!attk --button PRIMARY|'+tokenID+'|'+itemIndex+'|0||silent');
+ }
+ itemIndex = InHand.tableLookup( fields.InHand_index, 1 );
+ if (itemIndex.length && !isNaN(itemIndex)) {
+ LibFunctions.sendAPI('!attk --button OFFHAND|'+tokenID+'|'+itemIndex+'|1||silent');
+ }
+ itemIndex = InHand.tableLookup( fields.InHand_index, 2 );
+ if (itemIndex.length && !isNaN(itemIndex)) {
+ LibFunctions.sendAPI('!attk --button BOTH|'+tokenID+'|'+itemIndex+'|2||silent');
+ }
+
+ for (let r=3; !_.isUndefined(itemIndex = InHand.tableLookup( fields.InHand_index, r, false )); r++) {
+ if (itemIndex.length && !isNaN(itemIndex)) {
+ LibFunctions.sendAPI('!attk --button HAND|'+tokenID+'|'+itemIndex+'|'+r+'||silent');
+ }
+ }
+ return;
+ }
+
+
+/* --------------------------------------------------- End of Library Functions ---------------------------------------------------- */
+
+
+/* ---------------------------------------------------- Finish Initialisation ---------------------------------------------- */
+
+ LibFunctions.sendFeedback( 'Please wait while RPGMaster initialises... ' );
+ apis.magic = ('undefined' !== typeof MagicMaster);
+ apis.attk = ('undefined' !== typeof attackMaster);
+ apis.init = ('undefined' !== typeof initMaster);
+ DBindex = undefined;
+
+ setTimeout( del_Old_DBs, 5000 );
+
+ // RED: v1.036 create help handouts from stored data
+ setTimeout( () => LibFunctions.updateHandouts(handouts,true,findTheGM()),300);
+ setTimeout( () => displayReleaseNotesLink(), 5000 );
+ }
+ }
+
+ const handleChatMessage = (msg) => {
+ try {
+ var preamble, targetid,
+ playerid = msg.playerid;
+ if (msg.type === "api") {
+ return;
+ } else if (msg.content.trim().startsWith('!')) {
+ log('lib handleChatMessage: msg not api but starts with ! so re-send. Msg = '+msg.content);
+ sendChat('',processInlinerolls(msg),null,{noarchive:!archive, use3d:use3Ddice});
+ }
+ if (msg.rolltemplate && msg.rolltemplate.startsWith('RPGM')) {
+ targetid = findTheGM();
+ if (msg.target) {
+ if (msg.target != 'gm') {
+ let targetObjs = findObjs({_type:'player',_displayname:msg.who});
+ targetid = (!targetObjs || !targetObjs.length) ? findTheGM() : targetObjs[0].id;
+ }
+ }
+ let newMsg = Object.create(msg);
+ newMsg = processInlinerolls(newMsg);
+ const template = newMsg.match(/^([^{]*)({{[^]*}}).*?$([^]*)/im);
+ switch (msg.type) {
+ case 'emote':
+ preamble = '/em';
+ break;
+ case 'desc':
+ preamble = '/desc';
+ break;
+ case 'whisper':
+ preamble = '/w "'+msg.target_name+'"';
+ break;
+ default:
+ preamble = '';
+ break;
+ }
+ preamble += ' '+template[1];
+ LibFunctions.parseOutput( msg.who, preamble, msg.rolltemplate, template[2], targetid );
+ }
+ return;
+ } catch (e) {
+ log('RPGMaster Library handleChatMessage: JavaScript '+e.name+': '+e.message+' while processing a chat message');
+// sendDebug('RPGMaster Library handleChatMessage: JavaScript '+e.name+': '+e.message+' while processing a chat message');
+ LibFunctions.sendError('RPGMaster Library JavaScript '+e.name+': '+e.message);
+ }
+ };
+
+ const tryInit = ()=>{
+ if(Campaign()) {
+ LibFunctions.init();
+ } else {
+ setTimeout(tryInit,10);
+ }
+ };
+ setTimeout(tryInit,0);
+
+ const checkInstall = () => {
+ log('-=> libRPGMaster v'+version+' <=- ['+(new Date(lastUpdate*1000))+']');
+
+ if( ! state.hasOwnProperty('libRPGMaster') || state.libRPGMaster.version !== schemaVersion) {
+ switch(state.libRPGMaster && state.libRPGMaster.version) {
+
+ case 0.1:
+ /* break; // intentional dropthrough */
+
+ case 'UpdateSchemaVersion':
+ state.libRPGMaster.version = schemaVersion;
+ break;
+
+ default:
+ state.libRPGMaster = {
+ version: schemaVersion
+ };
+ break;
+ }
+ }
+ };
+
+ const registerLib = () => {
+ on('chat:message',handleChatMessage);
+ };
+
+ on('ready', function () {
+ checkInstall();
+ registerLib();
+ });
+
+ return {
+ getRPGMap: (...a) => LibFunctions.getRPGMap(...a),
+ getTableField: (...a) => LibFunctions.getTableField(...a),
+ getTable: (...a) => LibFunctions.getTable(...a),
+ getLvlTable: (...a) => LibFunctions.getLvlTable(...a),
+ initValues: (...a) => LibFunctions.initValues(...a),
+ attrLookup: (...a) => LibFunctions.attrLookup(...a),
+ setAttr: (...a) => LibFunctions.setAttr(...a),
+ abilityLookup: (...a) => LibFunctions.abilityLookup(...a),
+ setAbility: (...a) => LibFunctions.setAbility(...a),
+ doDisplayAbility: (...a) => LibFunctions.doDisplayAbility(...a),
+ getAbility: (...a) => LibFunctions.getAbility(...a),
+ parseTemplate: (...a) => LibFunctions.parseTemplate(...a),
+ redisplayOutput: (...a) => LibFunctions.redisplayOutput(...a),
+ parseOutput: (...a) => LibFunctions.parseOutput(...a),
+ sendToWho: (...a) => LibFunctions.sendToWho(...a),
+ sendPublic: (...a) => LibFunctions.sendPublic(...a),
+ sendAPI: (...a) => LibFunctions.sendAPI(...a),
+ sendFeedback: (...a) => LibFunctions.sendFeedback(...a),
+ sendResponse: (...a) => LibFunctions.sendResponse(...a),
+ sendResponsePlayer: (...a) => LibFunctions.sendResponsePlayer(...a),
+ sendResponseError: (...a) => LibFunctions.sendResponseError(...a),
+ sendToOthers: (...a) => LibFunctions.sendToOthers(...a),
+ sendError: (...a) => LibFunctions.sendError(...a),
+ sendParsedMsg: (...a) => LibFunctions.sendParsedMsg(...a),
+ sendGMquery: (...a) => LibFunctions.sendGMquery(...a),
+ checkDBver: (...a) => LibFunctions.checkDBver(...a),
+ saveDBtoHandout: (...a) => LibFunctions.saveDBtoHandout(...a),
+ buildCSdb: (...a) => LibFunctions.buildCSdb(...a),
+ checkCSdb: (...a) => LibFunctions.checkCSdb(...a),
+ getDBindex: (...a) => LibFunctions.getDBindex(...a),
+ updateHandouts: (...a) => LibFunctions.updateHandouts(...a),
+ getCharacter: (...a) => LibFunctions.getCharacter(...a),
+ getTokenValue: (...a) => LibFunctions.getTokenValue(...a),
+ classObjects: (...a) => LibFunctions.classObjects(...a),
+ addMIspells: (...a) => LibFunctions.addMIspells(...a),
+ getMagicList: (...a) => LibFunctions.getMagicList(...a),
+ getShownType: (...a) => LibFunctions.getShownType(...a),
+ handleCheckSaves: (...a) => LibFunctions.handleCheckSaves(...a),
+ handleCheckWeapons: (...a) => LibFunctions.handleCheckWeapons(...a),
+ getHandoutIDs: (...a) => LibFunctions.getHandoutIDs(...a),
+ classAllowedItem: (...a) => LibFunctions.classAllowedItem(...a),
+ resolveData: (...a) => LibFunctions.resolveData(...a),
+ findPower: (...a) => LibFunctions.findPower(...a),
+ handleGetBaseThac0: (...a) => LibFunctions.handleGetBaseThac0(...a),
+ characterLevel: (...a) => LibFunctions.characterLevel(...a),
+ caster: (...a) => LibFunctions.caster(...a),
+ };
+
+})();
+
+{try{throw new Error('');}catch(e){API_Meta.libRPGMaster.lineCount=(parseInt(e.stack.split(/\n/)[1].replace(/^.*:(\d+):.*$/,'$1'),10)-API_Meta.libRPGMaster.offset);}}
diff --git a/RPGMlibrary AD+D2e/libRPGMaster2e.js b/RPGMlibrary AD+D2e/libRPGMaster2e.js
index 2cf3fe0801..c1509ca17d 100644
--- a/RPGMlibrary AD+D2e/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/libRPGMaster2e.js
@@ -111,6 +111,9 @@
* v1.5.02 08/06/2023 Fixed issue with checkCSdb() when parsing spells/powers that are innate
* and weaponised.
* v1.5.03 13/06/2023 Fixed issue with self-hidden items being revealed incorrectly.
+ * v1.5.04 23/06/2023 Fixed issue with adding items to any character.
+ * v1.5.05 15/07/2023 Fixed issue with errors caused by tokens with un-linked token bars,
+ * especially with the calculations of attack success.
**/
var API_Meta = API_Meta||{}; // eslint-disable-line no-var
@@ -6107,7 +6110,7 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
}
}
}
- if (!ability || ability.length==0) {
+ if (!ability || ability.length==0 || ability === '-') {
return (!def ? new AbilityObj( rootDB, undefined, undefined, undefined) : new AbilityObj( rDB, [undefined,blankItem], [undefined,0], 'apiDB'));
}
@@ -7565,8 +7568,8 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
attrVal = !isNaN(attrVal) ? parseFloat(attrVal) : undefined;
}
if (isNaN(attrVal) && !linkedToken && fieldIndex >= 0) {
- attrVal = parseFloat(curToken.get('bar'+fieldIndex+'_'+token_property));
- attrName = barName = 'bar'+fieldIndex;
+ attrName = barName = 'bar'+(fieldIndex+1);
+ attrVal = parseFloat(curToken.get(barName+'_'+token_property));
}
if (isNaN(attrVal) && attr.includes('thac0')) {
if (!thac0_base) thac0_base = ['thac0-base','current','20'];
diff --git a/RPGMlibrary AD+D2e/script.json b/RPGMlibrary AD+D2e/script.json
index 442cd49fc1..421dd389fa 100644
--- a/RPGMlibrary AD+D2e/script.json
+++ b/RPGMlibrary AD+D2e/script.json
@@ -2,8 +2,8 @@
"$schema": "https://github.com/DameryDad/roll20-api-scripts/blob/RPGMlibrary/RPGMlibrary AD+D2e/Script.json",
"name": "RPGMaster library AD+D2e",
"script": "libRPGMaster2e.js",
- "version": "1.5.04",
- "previousversions": ["1.3.00","1.3.01","1.3.02","1.3.03","1.3.04","1.4.01","1.4.02","1.4.03","1.4.04","1.4.05","1.4.06","1.4.07","1.5.01","1.5.02","1.5.03"],
+ "version": "1.5.05",
+ "previousversions": ["1.3.00","1.3.01","1.3.02","1.3.03","1.3.04","1.4.01","1.4.02","1.4.03","1.4.04","1.4.05","1.4.06","1.4.07","1.5.01","1.5.02","1.5.03","1.5.04"],
"description": "RPGMaster Library for AD&D2e provides all of the game-version-specific data and rule processing for the RPGMaster series of APIs to work with the Advanced Dungeon & Dragons 2nd Edition rule set, and with the Advanced D&D2e Character Sheet by Peter B. Other versions of the library will support other gave versions in future. In order for versions of the RPGMaster series APIs later than 1.0.0 to work (i.e. those that have version numbers with three segments) they require one of the RPGMaster Libraries to be loaded with them: which one determines which rule set and character sheet they work with. The Library does not support any API commands itself (the other RPGMaster APIs provide those), but it supports a unique set of Roll Templates, and provides API Authors with a number of callable functions that might be of use. See the RPGMaster Library Help handout that the Library creates in your campaign when initially loaded for details.\n\n[RPGMaster Documentation](https://wiki.roll20.net/RPGMaster) \n### Getting Started\n1. When all APIs in the RPGMaster suite are loaded, run `!cmd --initialise` and add the player macros created to the Macro Bar, then\n2. Select tokens and use the `Token Setup` macro bar button just created to add all relevant Action Buttons to the token(s) (plus set the tokens/Characters up in any other way provided in the menu displayed) \n3. Once steps 1 & 2 have been done, the players and DM can then use the buttons displayed at the top of the screen when their character's token is selected to perform all actions needed in normal play.",
"authors": "Richard E.",
"roll20userid": "6497708",
From 46cfc71e0e33fe438b0a0e4ec2686d8af15a5f19 Mon Sep 17 00:00:00 2001
From: DameryDad <74715860+DameryDad@users.noreply.github.com>
Date: Sat, 15 Jul 2023 12:02:50 +0100
Subject: [PATCH 2/2] Fixed classObjects() with multi-class
* Fixed classObjects() error in classData[] return for multi-class characters
---
RPGMlibrary AD+D2e/1.5.05/libRPGMaster2e.js | 9 +++++----
RPGMlibrary AD+D2e/libRPGMaster2e.js | 9 +++++----
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/RPGMlibrary AD+D2e/1.5.05/libRPGMaster2e.js b/RPGMlibrary AD+D2e/1.5.05/libRPGMaster2e.js
index c1509ca17d..2991ce1dec 100644
--- a/RPGMlibrary AD+D2e/1.5.05/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/1.5.05/libRPGMaster2e.js
@@ -113,7 +113,8 @@
* v1.5.03 13/06/2023 Fixed issue with self-hidden items being revealed incorrectly.
* v1.5.04 23/06/2023 Fixed issue with adding items to any character.
* v1.5.05 15/07/2023 Fixed issue with errors caused by tokens with un-linked token bars,
- * especially with the calculations of attack success.
+ * especially with the calculations of attack success. Fixed classObjects()
+ * error in classData[] return for multi-class characters
**/
var API_Meta = API_Meta||{}; // eslint-disable-line no-var
@@ -122,9 +123,9 @@ API_Meta.libRPGMaster={offset:Number.MAX_SAFE_INTEGER,lineCount:-1};
const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
'use strict';
- const version = '1.5.03';
+ const version = '1.5.05';
API_Meta.libRPGMaster.version = version;
- const lastUpdate = 1686215927;
+ const lastUpdate = 1689326353;
const schemaVersion = 0.1;
log('now in seconds is '+Date.now()/1000);
@@ -7643,7 +7644,7 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
return {name:charClass.dbName(), dB:classObj.dB, base:baseClass.dbName(), dBbase:fields.ClassDB, level:charLevel, obj:classObj.obj};
});
if (_.isUndefined(classDef) || !classDef.length) classDef = [{name:'creature', base:'warrior', level:0, obj:LibFunctions.abilityLookup( fields.ClassDB, 'creature', charCS ).obj}];
- classDef = classDef.map(c => {[c.classData] = LibFunctions.resolveData(charClass, dB, reData);return c});
+ classDef = classDef.map(c => {[c.classData] = LibFunctions.resolveData(c.name, c.dB, reData);return c});
return classDef;
};
diff --git a/RPGMlibrary AD+D2e/libRPGMaster2e.js b/RPGMlibrary AD+D2e/libRPGMaster2e.js
index c1509ca17d..2991ce1dec 100644
--- a/RPGMlibrary AD+D2e/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/libRPGMaster2e.js
@@ -113,7 +113,8 @@
* v1.5.03 13/06/2023 Fixed issue with self-hidden items being revealed incorrectly.
* v1.5.04 23/06/2023 Fixed issue with adding items to any character.
* v1.5.05 15/07/2023 Fixed issue with errors caused by tokens with un-linked token bars,
- * especially with the calculations of attack success.
+ * especially with the calculations of attack success. Fixed classObjects()
+ * error in classData[] return for multi-class characters
**/
var API_Meta = API_Meta||{}; // eslint-disable-line no-var
@@ -122,9 +123,9 @@ API_Meta.libRPGMaster={offset:Number.MAX_SAFE_INTEGER,lineCount:-1};
const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
'use strict';
- const version = '1.5.03';
+ const version = '1.5.05';
API_Meta.libRPGMaster.version = version;
- const lastUpdate = 1686215927;
+ const lastUpdate = 1689326353;
const schemaVersion = 0.1;
log('now in seconds is '+Date.now()/1000);
@@ -7643,7 +7644,7 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
return {name:charClass.dbName(), dB:classObj.dB, base:baseClass.dbName(), dBbase:fields.ClassDB, level:charLevel, obj:classObj.obj};
});
if (_.isUndefined(classDef) || !classDef.length) classDef = [{name:'creature', base:'warrior', level:0, obj:LibFunctions.abilityLookup( fields.ClassDB, 'creature', charCS ).obj}];
- classDef = classDef.map(c => {[c.classData] = LibFunctions.resolveData(charClass, dB, reData);return c});
+ classDef = classDef.map(c => {[c.classData] = LibFunctions.resolveData(c.name, c.dB, reData);return c});
return classDef;
};
|