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:
v8.02 07/05/2024 Updated spell effects to use latest features, e.g. save mod table
v8.01 13/04/2024 Split spells by level into separate databases for easier management.
For earlier changes, see PR-Spells-DB-L1',
+ controlledby:'all',
+ root:'PR-Spells-DB',
+ type:'spells',
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/163483347/1CLiNzi4jlxXK1-lVr7MTQ/max.png?1599726214',
+ version:8.02,
+ db:[{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|pr-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|pr-casting-level}]] rounds}}{{aoe=[[[2*@{selected|pr-casting-level}]] cu.ft.](!rounds --movable-aoe @{selected|token_id}|rectangle|feet|120|||magic --target-nosave caster|@{selected|token_id}|Animate-Rock|@{selected|pr-casting-level}|-1|Animated a rock which will obay simple commands|edge-crack)}}{{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*](!magic --display-ability @{selected|token_id}|PR-Spells-DB|animate-object) spell.), following the desire of the caster--attacking, breaking objects, blocking--while the magic lasts.}}{{hide1=It has no intelligence or volition of its own, but it follows instructions exactly as spoken. Only one set of instructions for one single action can be given to the animated rock, and the directions must be brief, about a dozen words or so. The rock remains animated for one round per experience level of the caster. The volume of rock that can be animated is also based on the experience level of the caster--2 cubic feet of stone per level, such as 24 cubic feet, a mass of about man-sized, at 12th level.\nWhile the exact details of the animated rock are decided by the DM, its Armor Class is no worse than 5, and it has 1d3 hit points per cubic foot of volume. It uses the attack roll of the caster. The maximum damage it can inflict is 1d2 points per caster level. Thus, a 12th-level caster\'s rock might inflict 12 to 24 points of damage. Movement for a mansized rock is 60 feet per round. A rock generally weighs from 100 to 300 pounds per cubic foot.}}{{materials=A stone and drop of the caster\'s blood, costing nothing}}{{Use=Click the *area of effect* button to set a caster status timer (requires use of the Turn Order or *GM Maint menu* to increment round number) and specify the dimensions of the resulting rock. The token created can be then moved by the caster}}'},
+ {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|pr-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.}}{{hide1=As the Astral plane touches upon the first levels of all the outer planes, the priest can travel astrally to the first level of any of these outer planes as he wills. The priest then leaves the Astral plane, forming a body on the plane of existence he has chosen to enter. It is also possible to travel astrally anywhere in the Prime Material plane by means of the astral spell. However, a second body cannot be formed on the Prime Material plane.\nAs a general rule, a person astrally projected can be seen only by creatures on the Astral plane. The astral body is connected at all times to the material body by a silvery cord. If the cord is broken, the affected person is killed, astrally and materially, but generally only the psychic wind can cause the cord to break. When a second body is formed on a different plane, the silvery cord remains invisibly attached to the new body. If the second body or astral form is slain, the cord simply returns to the caster\'s body where the body rests on the Prime Material plane, reviving it from its state of suspended animation. Although astral projections are able to function on the Astral plane, their actions affect only creatures existing on the Astral plane; a physical body must be materialized on other planes.\nThe spell lasts until the priest desires to end it, or until it is terminated by some outside means, such as dispel magic spell or destruction of the priest\'s body on the Prime Material plane--which kills the priest. The priest can project the astral forms of up to seven other creatures with himself by means of the astral spell, providing the creatures are linked in a circle with the priest. These fellow travelers are dependent upon the priest and can be stranded if something happens to the priest. Travel in the Astral plane can be slow or fast, according to the priest\'s desire. The ultimate destination arrived at is subject to the desire of the priest.}}'},
+ {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|pr-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|pr-casting-level} turns](!rounds --target caster|@{selected|token_id}|Changestaff|[[10*@{selected|pr-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.}}{{hide1=When the priest plants the end of the staff in the ground and speaks a special command and invocation, the staff turns into a treantlike creature with 12 Hit Dice, 40 hit points, and Armor Class 0. It attacks twice per round, inflicting 4d6 points of damage with every successful attack. The staff-treant defends the caster and obeys any spoken commands. However, it is by no means a true treant; it cannot converse with actual treants or control trees. The transformation lasts either for as many turns as the caster has experience levels, until the caster commands the staff to return to its true form, or until the staff is destroyed, whichever occurs first. If the staff-treant is reduced to 0 hit points or less, it crumbles to a sawdustlike powder and the staff is destroyed. Otherwise, the staff can be used again after 24 hours and the stafftreant is at full strength.\nTo cast a *changestaff* spell, the caster must have either his holy symbol or leaves (ash, oak, or yew) of the same sort as the staff.\nThe staff for the *changestaff* spell must be specially prepared. The staff must be a sound limb cut from an ash, oak, or yew tree struck by lightning no more than 24 hours before the limb is cut. The limb must then be cured by sun drying and special smoke for 28 days. Then it must be shaped, carved, and polished for another 28 days. The caster cannot adventure or engage in other strenuous activity during either of these periods. The finished staff, engraved with woodland scenes, is then rubbed with the juice of holly berries, and the end of it is thrust into the earth of the caster\'s grove while he casts a speak with plant spell, calling upon the staff to assist in time of need. The item is then charged with a magic that will last for many changes from staff to treant and back again.}}{{materials=Either his holy symbol or leaves (ash, oak, or yew) of the same sort as the staff (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|pr-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}}{{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.}}{{hide1=The vehicle moves at 24 on the ground, 48 flying, and can carry the caster and up to seven other creatures of man-size or less. The passengers must be touched by the caster to protect them from the flames of the chariot. Creatures other than the caster and his designated passengers sustain 2d4 points of fire damage each round if they come within 5 feet of the horses or chariot. Such creatures suffer no damage if they evade the area by rolling successful saving throws vs. petrification, with Dexterity adjustments.\nThe caster controls the chariot by verbal command, causing the flaming steeds to stop or go, walk, trot, run or fly, and turn left or right as he desires. Note that the *chariot of Sustarre* is a physical manifestation and can sustain damage. The vehicle and steeds are struck only by magical weapons or by water (one quart of which inflicts 1 point of damage). They are Armor Class 2, and each requires 30 points of damage to dispel. Naturally, fire has no effect upon either the vehicle or its steeds, but magical fires other than those of the chariot can affect the riders. Other spells, such as a successful *dispel magic* or *holy word*, will force the chariot back to its home plane, without its passengers. The chariot can be summoned only once per week.}}{{materials=A small piece of wood, two holly berries, and a fire source at least equal to a torch. Total cost 1cp}}'},
+ {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|pr-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|pr-casting-level}]] rounds}}{{aoe=[[[1d4+floor(@{selected|pr-casting-level}/2)]] creatures](!rounds --target multi|@{selected|token_id}|\\amp#64;{target|Who\'s confused?|token_id}|Confusion|@{selected|pr-casting-level}|-1|This is so confusing! This round roll is 1d10|broken-skull|svspe\\clon;-2) in [40ft.sq.](!rounds --aoe @{selected|token_id}|square|feet|240|40||magic)}}{{save=Negates}}{{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.}}{{hide1=The spell affects 1d4 creatures, plus one creature per two caster levels. Thus, seven to ten creatures can be affected by a 12th or 13th-level caster, eight to 11 by a 14th- or 15th-level caster, etc. These creatures are allowed saving throws vs. spell with -2 penalties, adjusted for Wisdom. Those successfully saving are unaffected by the spell. Confused creatures react as follows (roll 1d10):\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th width="15%"\\ampgt;d10\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Reaction\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;1\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Wander away (unless prevented) for duration of spell\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;2-6\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stand confused one round (then roll again)\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;7-9\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Attack nearest creature for one round (then roll again)\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;10\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Act normally for one round (then roll again)\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nThe spell lasts one round for each level of the caster. Those who fail their saving throws are checked by the DM for actions each round, for the duration of the spell, or until the "wander away for the duration of the spell" result occurs.\nWandering creatures move as far from the caster as possible in their most typical mode of movement (characters walk, fish swim, bats fly, etc.). This is not panicked flight. Wandering creatures also have a 50% chance of using any special innate movement abilities (plane shift, burrowing, flight, etc.). Saving throws and actions are checked at the beginning of each round. Any confused creature that is attacked perceives the attacker as an enemy and acts according to its basic nature.}}{{GM Info=If there are many creatures involved, the DM may decide to assume average results. For example, if there are 16 orcs affected and 25% could be expected to successfully roll the saving throw, then four are assumed to have succeeded, one wanders away, four attack the nearest creature, six stand confused and the last acts normally but must check next round. Since the orcs are not near the party, the DM decides that two who are supposed to attack the nearest creature attack each other, one attacks an orc that saved, and one attacks a confused orc, which strikes back. The next round, the base is 11 orcs, since four originally saved and one wandered off. Another one wanders off, five stands confused, four attack, and one acts normally.}}{{materials=A set of three nut shells, costing 1cp to source}}'},
+ {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|pr-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|pr-casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Conjure-Earth-Elemental|[[10*@{selected|pr-casting-level}]]|-1|The Earth Elemental continues to do your bidding... for now|fist)}}{{time=[[1]] turn}}{{aoe=Special}}{{save=None}}{{reference=PHB p232}}{{use=The DM should *Drag \\amp Drop* the relevant earth elementals onto the playing surface once the spell is cast}}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).}}{{hide1=Further, the caster needs but to command it, and it does as desired. The elemental regards the caster as a friend to be obeyed. The elemental remains until destroyed, dispelled, sent away by dismissal or a holy word spell (see the conjure fire elemental spell), or the spell duration expires.}}'},
+ {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|pr-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.}}{{hide1=The spell affects the weather for 4d12 hours in an area of 4d4 square miles. It requires one turn to cast the spell, and an additional 1d4 turns for the effects of the spell to be felt. The current weather conditions are decided by the DM, depending on the climate and season. Weather conditions have three components: precipitation, temperature, and wind. The spell can change these conditions according to the following chart:\\amplt;table\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;Precipitation\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Temperature\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Wind\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;**CLEAR WEATHER**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**HOT**\\amplt;/td\\ampgt;\\amplt;td\\ampgt; **CALM**\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Very clear\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Sweltering heat\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Dead calm\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Light clouds or hazy\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Warm\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Light wind\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Moderate wind\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;**PARTLY CLOUDY**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**WARM**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**MODERATE WIND**\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Clear weather\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Hot\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Calm\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Cloudy\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Cool\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Strong wind\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Mist/light rain/small hail\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Sleet/light snow\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;**CLOUDY**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**COOL**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**STRONG WIND**\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Partly cloudy\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Warm\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Moderate wind\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Deep Clouds\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Cold\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Gale\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Fog\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Heavy rain/large hail\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Driving sleet/Heavy snow\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;**COLD**\\amplt;/td\\ampgt;\\amplt;td\\ampgt;**GALE**\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Cool\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Strong wind\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Arctic cold\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Storm\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;**STORM**\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Gale\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Hurricane-typhoon\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nThe upper-case headings represent existing weather conditions. The lower-case headings below are the new conditions to which the caster can change the existing conditions. In addition, the caster can control the direction of the wind. For example, a day that is clear, warm, and with moderate wind can be controlled to become hazy, hot, and calm. Contradictions are not possible--fog and strong wind, for example. Multiple control weather spells can be used only in succession.\nThe material components for this spell are the priest\'s religious symbol, incense, and prayer beads or similar prayer object. Obviously, the spell functions only in areas where there are appropriate climatic conditions.\nIf Weather is a major sphere for the priest (as it is for druids), duration and area are doubled, and the caster can change the prevailing weather by two places. For example, he can cause precipitation to go from partly cloudy to heavy sleet, temperature to go from cool to arctic, and wind to go from calm to strong.}}{{materials=The priest\'s religious symbol, incense, and prayer beads or similar prayer object, total cost 5sp per casting}}'},
+ {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|pr-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|pr-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.}}{{hide1=This carpetlike mass swarms in an area 20 feet square. Upon command from the caster, the swarm creeps forth at 10 feet per round toward any prey within 80 yards, moving in the direction in which the caster commands. The creeping doom slays any creature subject to normal attacks, as each of the small horrors inflicts 1 point of damage (each then dies after its attack), so that up to 1,000 points of damage can be inflicted on creatures within the path of the creeping doom. If the creeping doom travels more than 80 yards away from the summoner, it loses 50 of its number for each 10 yards beyond 80 yards. For example, at 100 yards, its number has shrunk by 100. There are a number of ways to thwart or destroy the creatures forming the swarm. The solutions are left to the imaginations of players and DMs.}}'},
+ {name:'Destruction',type:'innate-melee|prspelll7',ct:'1',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nDestruction\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Destruction,Innate-Melee|PRspellL7,1H,Necromancy]{{components=V,S,M}}ToHitData=[w:Destruction,sb:0,r:5,ty:SPB,sp:1,touch:1,msg:A successful hit will require the victim to make a saving throw vs. death magic at a -4 penalty or be turned to dust. Successfully saving still does damage]{{range=Touch}}DmgData=[w:Destruction,sb:0,SM:8d6,L:8d6,msg:A successful hit will require the victim to make a saving throw vs. death magic at a -4 penalty or be turned to dust. Successfully saving still does damage]{{time=[[1]] turn}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=vs. death magic at -4 penalty}}{{reference=PHB p235 (reverse *resurrection*)}}SpellData=[w:Destruction,lv:7,sp:1,gp:0.1,cs:VSM,sph:Necromantic]{{Use=Take the spell in-hand when cast using the *change weapon* dialog, then attack the target. On a successful hit, the target should make a saving throw vs. death magic with a -4 penalty or be utterly destroyed. Successfully saving still takes 8d6 damage}}{{effects=*Destruction* causes the victim of the spell to be instantly dead and turned to dust. A wish spell or equivalent is required for recovery. Destruction requires a touch, either in combat or otherwise, and does not age the caster. In addition, the victim is allowed a saving throw (with a -4 penalty). If the save is successful, the victim receives [8d6](!\\amp#13;\\amp#47;gr 8d6) points of damage instead.}}{{materials=A prayer device and unholy water}}'},
+ {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|pr-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\n(reverse *conjure earth elemental*)}}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:'Earthquake',type:'prspelll7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEarthquake\nas a level @{selected|pr-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|pr-casting-level}]]ft diameter](!rounds --aoe @{selected|token_id}|circle|feet|360|[[5*@{selected|pr-casting-level}]]||lightning)}}{{save=Special}}{{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.}}{{hide1=The earthquake affects all terrain, vegetation, structures, and creatures in its area of effect. The area of effect of the earthquake spell is circular, with a diameter of 5 feet for every experience level of the priest casting it. Thus a 20th level priest casts an earthquake spell with a 100-foot-diameter area of effect.\nSolidly built structures with foundations reaching down to bedrock sustain one-half damage; one-quarter damage if they score above 50% on a saving throw. An earth elemental opposed to the caster in the area of effect can negate 10% to 100% (roll 1d10, 0 = 100%) of the effect. Other magical protections and wards allowed by the DM may also reduce or negate this effect. If cast undersea, this spell may, at the discretion of the DM, create a tsunami or tidal wave.\n**Earthquake Effects**\nTERRAIN\n**Cave or cavern**--Collapses roof\n**Cliffs**--Crumble, causing landslide\n**Ground**--Cracks open, causing the following fractions of creatures to fall in and die:\nSize S: 1 in 4\nSize M: 1 in 6\nSize L: 1 in 8\n**Marsh**--Drains water to form muddy, rough ground.\n**Tunnel**--Caves in\nVEGETATION\n**Small growth**--No effect\n**Trees**--1 in 3 are uprooted and fall\nSTRUCTURES\n**All structures**--Sustain 5d12 points of structural damage; those suffering full damage are thrown down in rubble\nCREATURES (See TERRAIN entry)}}{{materials=A pinch of dirt, a piece of rock, and a lump of clay (no cost)}}'},
+ {name:'Energy-Drain',type:'innate-melee|prspelll7',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nEnergy Drain\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Energy Drain,Innate-Melee|PRspellL7,1H,Necromancy]{{components=V,S}}ToHitData=[w:Energy Drain,sb:0,r:5,ty:SPB,sp:1,touch:1,msg:A successful hit will \\lbrak;drain\\rbrak;\\lpar;!magic ~~level-change \\amp#64;{target\\vbar;Who will be Drained?\\vbar;token_id}\\vbar;-1\\rpar; the victim of 1 life energy level]{{range=Touch}}DmgData=[w:Energy Drain,sb:0,SM:0,L:0,msg:A successful hit will \\lbrak;drain\\rbrak;\\lpar;!magic ~~level-change \\amp#64;{target\\vbar;Who will be Drained?\\vbar;token_id}\\vbar;-1\\rpar; the victim of 1 life energy level]{{time=[[3]] rounds}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=None}}{{reference=PHB p235 (reverse *restoration*)}}SpellData=[w:Energy Drain,lv:7,sp:30,gp:0,cs:VS,sph:Necromantic]{{Use=Take the spell in-hand when cast using the *change weapon* dialog, then attack the target. On a successful hit, use the *drain* button displayed (if dual- or multi-classed will ask it\'s desired class to drain)}}{{effects=*Energy drain* draws away one life energy level (see such undead as spectre, wight, and vampire, in the Monstrous Manual). The energy drain requires the victim to be touched. Casting this form of the spell does not age the caster.}}'},
+ {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|pr-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.}}{{hide1=A creature of an alignment opposed to the priest (e.g., evil if the priest is good, chaotic if the priest is lawful) cannot be ordered around unless it is willing. Note that an absolute (true) neutral creature is effectively opposed to both good and evil, and both law and chaos.\nThe spellcaster must know something about the creature to exact service from it, or else he must offer some fair trade in return for the service. That is, if the priest is aware that the creature has received some favor from someone of the priest\'s alignment, then the exaction spell can name this as cause. If no balancing reason for service is known, then some valuable gift or service must be pledged in return for the exaction. The service exacted must be reasonable with respect to the past or promised favor or reward, and with the being\'s effort and risk. The spell then acts, subject to a magic resistance roll, as a quest upon the being that is to perform the required service. Immediately upon completion of the service, the being is transported to the vicinity of the priest, and the priest must then and there return the promised reward, whether it is irrevocable cancellation of a past debt or the giving of some service or other material reward. After this is done, the creature is instantly freed to return to its own plane.\nThe DM adjudicates when an equitable arrangement has been reached. If the caster requests too much, the creature is free to depart or to attack the priest (as if the agreement were breached) according to its nature. If circumstances leave the situation unbalanced (for example, the creature dies while achieving a result that was not worth dying for), then this might create a debt owed by the caster to the creature\'s surviving kith and kin, making the caster vulnerable to a future exaction spell from that quarter. Agreeing to a future exaction or release in the event of catastrophic failure or death are common caster pledges in securing an exaction.\nFailure to fulfill the promise to the letter results in the priest being subject to exaction by the subject creature or by its master, liege, etc., at the very least. At worst, the creature can attack the reneging priest without fear of any of his spells affecting it, for the priest\'s failure to live up to the bargain gives the creature immunity from the priest\'s spell powers.}}{{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:'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|pr-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|pr-casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||cold)\nor vs. normal [[[4*@{selected|pr-casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||cold)}}{{save=Special}}{{reference=PHB p234 (reverse *fire storm*)}}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.}}{{hide1=Fire-based creatures, such as elementals, salamanders, etc., of less than demigod status have a 5% chance per experience level of the caster of being extinguished. If cast only against a flametongue sword, the sword must roll a successful saving throw vs. crushing blow or be rendered nonmagical. Such a sword in the possession of a creature first receives the creature\'s saving throw, and if this is successful, the second saving throw is automatically successful.}}'},
+ {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|pr-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|pr-casting-level}]] x 10ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|480|||fire)}}{{save=Halves}}{{damage=[2d8 + @{selected|pr-casting-level}](!\\amp#13;\\amp#47;r 2d8+@{selected|pr-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.}}{{hide1=Creatures within the area of fire and 10 feet or less from the edge of the affected area receive 2d8 points of damage plus additional damage equal to the caster\'s level (2d8 +1/level). Creatures that roll successful saving throws vs. spell suffer only one-half damage. The damage is inflicted each round the creature stays in the area of effect. The area of effect is equal to two 10-foot x 10-foot cubes per level of the cater--e.g., a 13th-level caster can cast a fire storm measuring 130 feet x 20 feet x 10 feet. The height of the storm is 10 or 20 feet; the imbalance of its area must be in length and width.}}'},
+ {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|pr-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.}}{{hide1=Uttering the spell attracts the attention of the dweller on the other plane. When casting the spell, the priest must name the entity he desires to make use of the gate and to come to his aid. There is a 100% chance that something steps through the gate. The actions of the being that comes through depend on many factors, including the alignment of the priest, the nature of those accompanying him, and who or what opposes or threatens the priest. The DM will decide the exact result of the spell, based on the creature called, the desires of the caster and the needs of the moment. The being gates in either returns immediately or remains to take action. Casting this spell ages the priest five years.}}'},
+ {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|pr-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.}}{{hide1=Creatures so banished cannot return for at least a day. The spell further affects creatures of differing alignment as shown on the following table:\n**Effects of Holy Word**\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;Creature\'s Hit Dice or Level\\amplt;/th\\ampgt;\\amplt;th\\ampgt;General\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Attack Move\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Dice\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Spells\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Less than 4\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Kills\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;4 to 7+\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Paralyzes 1d4 turns](!rounds --target multi|@{selected|token_id}|Paralysis|\\amp#91;[10*1d4]\\amp#93;|-1|Paralysed by the Holy Word|fishing-net)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;8 to 11+\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Slows 2d4 rounds](!rounds --target multi|@{selected|token_id}|Slow_Holy Word|\\amp#91;[2d4]\\amp#93;|-1|Slowed by @{selected|token_name}\'s Holy Word|snail)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-50%\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-4^\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;12 or more\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Deafens 1d4 rounds](!rounds --target multi|@{selected|token_id}|Deafness_Holy Word|\\amp#91;[1d4]\\amp#93;|-1|Deafened by @{selected|token_name}\'s Holy Word|bleeding-eye)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-25%\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;50% chance\nof failure\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\n^Slowed creatures attack only on even-numbered rounds until the effect wears off.\nAffected creatures are those within the 30-foot-radius area of effect, which is centered on the priest casting the spell. The side effects are negated for deafened or silenced creatures, but such are still driven off if other-planar.}}'},
+ {name:'Regenerate',type:'prspelll7',ct:'30',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRegenerate\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Regenerate,PRspellL7,1H,Necromancy]{{components=V,S,M}}{{range=Touch}}{{time=[[3]] rounds}}{{duration=Permanent}}{{aoe=Creature Touched}}{{save=None}}{{reference=PHB p234}}SpellData=[w:Regenerate,lv:7,sp:30,gp:0.1,cs:VSM,sph:Necromantic]{{Use=Select the relevant button in the description and then select the token that is regenerating lost limbs}}{{effects=Body members (fingers, toes, hands, feet, arms, legs, tails, or even heads of multi-headed creatues), bones, and organs grow back. The process of regeneration requies but one round if the severed member(s) is (are) [present](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who will regenerate limbs?|token_id}|Regenerate|1|-1|Regenerating / reattaching severed parts|aura) and touching the creature, 2d4 turns [otherwise](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who will regenerate limbs?|token_id}|Regenerate|\\amp#91;[2d4]\\amp#93;|-1|Regenerating severed parts|aura). The creature must be living to receive the benefits of this spell. If the severed member is not present, or if the injury is older than one day per caster level, the recipient must roll a successful system shock check to survive the spell.}}{{materials=A prayer device and holy water}}'},
+ {name:'Reincarnate',type:'prspelll7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nReincarnate\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy}}{{sphere=Necromantic}}Specs=[Reincarnate,PRspellL7,1H,Necromancy]{{components=V,S}}{{range=Touch}}{{time=[[1]] turn}}{{duration=Permanent}}{{aoe=1 person}}{{save=None}}{{reference=PHB p234}}SpellData=[w:Reincarnate,lv:7,sp:100,gp:0,cs:VS,sph:Necromantic]{{effects=Brings back a dead person in another body, if death occurred no more than one week before the casting of the spell. Reincarnation does not require any saving throw, system shock, or resurrection survival roll.}}{{hide1=The corpse is touched, and a new incarnation of the person appears in the area in 1d6 turns. The person reincarnated recalls the majority of his former life and form, but the character class, if any, of the new incarnation might be very different indeed.The new incarnation is determined on the following table or by DM choice. At the DM\'s option, certain special (expensive) incenses can be used that may increase the chance for a character to return as a specific race or species. A *wish* spell can restore a reincarnated character to its original form and status.\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th scope="col"\\ampgt;D100 Roll\\amplt;/th\\ampgt;\\amplt;th scope="col"\\ampgt;Incarnation\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;01-03\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Badger\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;04-08\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Bear, Black\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;09-12\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Bear, Brown\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;13-16\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Boar, Wild\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;17-19\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Centaur\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;20-23\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Dryad\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;24-28\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Eagle\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;29-31\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Elf\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;32-34\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Faub/Satyr\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;35-36\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Fox\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;37-40\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Gnome\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;41-44\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Hawk\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;45-58\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Human\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;59-61\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Lynx\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;62-64\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Owl\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;65-68\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Pixie\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;69-70\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Raccoon\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;71-75\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stag\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;76-80\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Wolf\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;81-85\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Wolverine\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;86-00\\amplt;/td\\ampgt;\\amplt;td\\ampgt;DM\'s choice\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;If an unusual creature form is indicated, the DM can (at his option only) use the guidelines for new player character races to allow the character to earn experience and advance in levels, although this may not be in the same class as before. If the reincarnated character returns as a creature eligible to be the same class as he was previously (i.e., a human fighter returns as an elf), the reincarnated character has half his previous levels and hit points. If the character returns as a new character class, his hit points are half his previous total, but he must begin again at 1st level. If the character returns as a creature unable to have a class, he has half the hit points and saving throws of his previous incarnation.}}'},
+ {name:'Restoration',type:'prspelll7',ct:'30',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nRestoration\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Restoration,PRspellL7,1H,Necromancy]{{components=V,S}}{{range=Touch}}{{time=[[3]] rounds}}{{duration=Permanent}}{{aoe=[1 Creature](!magic --level-change \\amp#64;{target|Who will be Restored?|token_id}|+1)}}{{save=None}}{{reference=PHB p235}}SpellData=[w:Restoration,lv:7,sp:30,gp:0,cs:VS,sph:Necromantic]{{Use=Select the *area of effect* button above and then select the token of the creature to be restored to raise it by 1 level (if dual- or multi-classed will ask it\'s desired class)}}{{effects=The life energy level of the recipient creature is raised by one. This reverses any previous life energy level drain of the creature by a force or monster.}}{{hide1=Thus, if a 10th-level character had been struck by a wight and drained to 9th level, the *restoration* spell would bring the character up to exactly the number of experience points necessary to restore him to 10th level once again, restoring additional Hit Dice (or hit points) and level functions accordingly. Restoration is effective only if the spell is cast within one day of the recipient\'s loss of life energy, per experience level of the priest casting it. A *restoration* spell restores the intelligence of a creature affected by a *feeblemind* spell. It also negates all forms of insanity. Casting this spell ages both the caster and the recipient by two years.}}'},
+ {name:'Resurrection',type:'prspelll7',ct:'100',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nResurrection\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Resurrection,PRspellL7,1H,Necromancy]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] turn}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=None}}{{reference=PHB p235}}SpellData=[w:Resurrection,lv:7,sp:100,gp:0.1,cs:VSM,sph:Necromantic]{{effects=The priest is able to restore life and complete strength to any living creature, including elves, by bestowing the resurrection spell. The creature can have been dead up to 10 years per level of the priest casting the spell.}}{{hide1=Thus, a 19th-level priest can resurrect the bones of a creature dead up to 190 years. The creature, upon surviving a resurrection survival check, is immediately restored to full hit points and can perform strenuous activity. The spell cannot bring back a creature that has reached its allotted life span (i.e., died of natural causes). Casting this spell makes it impossible for the priest to cast further spells or engage in combat until he has had one day of bed rest for each experience level or Hit Die of the creature brought back to life. The caster ages three years upon casting this spell.}}{{materials=A prayer device and holy water}}'},
+ {name:'Reverse-Succor',type:'prspelll7',ct:'10',charge:'uncharged',cost:'4000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSuccor (Reversed)\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration / Enchantment (Reversable)}}{{sphere=Summoning}}Specs=[Reverse Succor,PRspellL7,1H,Alteration|Enchantment]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] day}}{{duration=Special}}{{aoe=1 person}}{{save=None}}{{reference=PHB p235 (reverse *succor*)}}SpellData=[w:Reverse Succor,lv:7,sp:10,gp:4000,cs:VSM,sph:Summoning]{{effects=By casting this spell, the priest creates a powerful magic aura in some specially prepared object--a string of prayer beads, a small clay tablet, an ivory baton, etc. This object radiates magic, for it contains the power to instantaneously transport the priest who created it from their sanctuary to the immediate vicinity of the possessor of the item when it is broken and the command word said.}}{{hide1=The priest has a general idea of the location and situation of the item\'s possessor, and can choose not to be affected by this summons. This decision is made at the instant when the transportation is to take place. However, if he chooses not to go, the opportunity is gone forever and the spell is wasted.\nNote that the same factors that can prevent the operation of the plane shift and teleport spells can also prevent the use of this spell.}}{{materials=The cost of preparing the special item (for either version of the spell) varies from 2,000 to 5,000 gp. The more costly items can transport the subject from one plane of existence to another, if the DM allows.}}'},
+ {name:'Succor',type:'prspelll7',ct:'10',charge:'uncharged',cost:'4000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSuccor\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration / Enchantment (Reversable)}}{{sphere=Summoning}}Specs=[Succor,PRspellL7,1H,Alteration|Enchantment]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] day}}{{duration=Special}}{{aoe=1 person}}{{save=None}}{{reference=PHB p235}}SpellData=[w:Succor,lv:7,sp:10,gp:4000,cs:VSM,sph:Summoning]{{effects=By casting this spell, the priest creates a powerful magic aura in some specially prepared object--a string of prayer beads, a small clay tablet, an ivory baton, etc. This object radiates magic, for it contains the power to instantaneously transport its possessor to the sanctuary of the priest who created its magic.}}{{hide1=Once the item is enchanted, the priest must give it willingly to an individual, at the same time informing him of a command word to be spoken when the item is to be used. To make use of the item, the recipient must speak the command word at the same time that he rends or breaks the item. When this is done, the individual and all that he is wearing and carrying (up to the maximum encumbrance limit for the character) are instantly transported to the sanctuary of the priest, just as if the individual were capable of speaking a *word of recall* spell. No other creatures can be affected.\nNote that the same factors that can prevent the operation of the plane shift and teleport spells can also prevent the use of this spell.}}{{materials=The cost of preparing the special item (for either version of the spell) varies from 2,000 to 5,000 gp. The more costly items can transport the subject from one plane of existence to another, if the DM allows.}}'},
+ {name:'Sunray',type:'prspelll7',ct:'4',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSunray\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Evocation / Alteration}}{{sphere=Sun}}Specs=[Sunray,PRspellL7,1H,Evocation|Alteration]{{components=V,S,M}}{{range=[[10*@{selected|pr-casting-level} yds.}}{{time=[[4]]}}{{duration=1+1d4 rounds}}{{aoe=[5 ft. radius](!rounds --aoe @{selected|token_id}|circle|feet|[[10*@{selected|pr-casting-level}]]|10|10|light) (special)}}{{save=Special}}{{reference=PHB p235}}SpellData=[w:Sunray,lv:7,sp:4,gp:1,cs:VSM,sph:Sun]{{Use=Select the *area of effect* button above and indicate where the beam will illuminate. Then apply the effects as described using the buttons to roll dice as relevant.}}{{effects=With this spell, the caster can evoke a dazzling beam of light each round in which they take no action other than movement. The sunray is like a ray of natural sunlight. All creatures in the 10-foot-diameter area of effect must roll successful saving throws vs. spell or be blinded for [1d3 rounds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creatures with normal vision are blinded?|token_id}|blinded|\\amp#91;[10*1d3]\\amp#93;|-10|Blinded by intense sunray. Attack and AC at -4 penalty|bleeding-eye), those using infravision at the time for [2d4 rounds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creatures using infravision are blinded?|token_id}|blinded|\\amp#91;[10*2d4]\\amp#93;|-10|Blinded by intense sunray. Attack and AC at -4 penalty|bleeding-eye). Creatures to whom sunlight is harmful or unnatural suffer [permanent blindness](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creatures that failed their save are permanently blinded?|token_id}|blinded|99|0|Blinded by intense sunray. Attack and AC at -4 penalty|bleeding-eye) if the saving throw is failed, and are blinded for [2d6 rounds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creatures to whom sunlight is unnatural are blinded?|token_id}|blinded|\\amp#91;[10*2d6]\\amp#93;|-10|Blinded by intense sunray. Attack and AC at -4 penalty|bleeding-eye) if the saving throw is successful. Those within its area of effect, as well as creatures within 20 feet of its perimeter, lose any infravision capabilities for [1d4+1 rounds](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creatures with infravision cannot now use it?|token_id}|Sunray|\\amp#91;[10*(1d4+1)]\\amp#93;|-10|Blinded by intense sunray. Cannot use infravision again yet|interdiction).\nUndead caught within the sunray\'s area of effect receive [8d6 points](!\\amp#13;\\amp#47;gr 8d6) of damage, one half if a saving throw vs. spell is successful. Those undead 20 feet to either side of the sunray\'s area of effect receive [3d6 points](!\\amp#13;\\amp#47;gr 3d6) of damage, no damage if a save is successful. In addition, the ray may result in the total destruction of those undead specifically affected by sunlight, if their saving throws are failed. \nThe ultraviolet light generated by the spell inflicts damage on fungoid creatures and subterranean fungi just as if they were undead, but no saving throw is allowed.}}{{materials=A prayer device and holy water}}'},
+ {name:'Symbol',type:'prspelll7',ct:'3',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nSymbol\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Conjuration Summoning}}{{sphere=Guardian}}Specs=[Symbol,PRspellL7,1H,Conjuration-Summoning]{{components=V,S,M}}{{range=Touch}}{{time=[[3]]}}{{duration=[[@{selected|pr-casting-level}]] turns}}{{aoe=60ft radius}}{{save=Negates}}{{reference=PHB p236}}SpellData=[w:Symbol,lv:7,sp:3,gp:10,cs:VSM,sph:Guardian]{{GM info=Cast this spell then\n1. Create a new Character Sheet and name it after the selected Symbol\n2. Drag the Symbol character sheet onto the map to drop a token where you want the symbol to be\n3. Use the Race/Class/Creature dialog, creature dropdown to make the token a creature: Symbol of Hopelessness, of Pain, or of Pursuasion\n4. [Mark the symbol](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Which is the symbol of Hopelessness?|token_id}|Symbol|@{selected|pr-casting-level}|-1|This is the symbol of hopelessness|lightning-helix) with it\'s duration by pressing this button and selecting the newly dropped symbol.\n5. When creatures view this token from less than 60ft away, use the powers on the symbol token to affect the viewing creature}}{{Use=Ask the GM to drop a symbol token onto the map for you by following the GM info instructions}}{{effects=The priest casting this spell inscribes a glowing symbol in the air upon any surface, according to his desire. Any creature looking at the completed symbol within 60 feet must roll a successful saving throw vs. spell or suffer the effect.}}{{hide1=The symbol glows for one turn for each experience level of the caster. The particular symbol used is selected by the caster at the time of casting. The caster will not be affected by his own symbol. One of the following effects is chosen by the caster:\n**Hopelessness:** Creatures seeing it must turn back in dejection or surrender to capture or attack unless they roll successful saving throws vs. spell. Its effects last for 3d4 turns.\n**Pain:** Creatures affected suffer -4 penalties to their attack rolls and -2 penalties to their Dexterity ability scores due to wracking pains. The effects last for 2d10 turns.\n**Persuasion:** Creatures seeing the symbol become of the same alignment as and friendly to the priest who scribed the symbol for 1d20 turns unless a saving throw vs. spell is successful.}}{{materials=The material components of this spell are mercury and phosphorous (see 8th-level wizard spell, *symbol*).}}'},
+ {name:'Transmute-Metal-to-Wood',type:'prspelll7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nTransmute Metal to Wood\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Elemental (Earth)}}Specs=[Transmute Metal to Wood,PRspellL7,1H,Alteration]{{components=V,S,M}}{{range=80 yds.}}{{time=[[1]] round}}{{duration=Permanent}}{{aoe=1 metal object of up to [[10*@{selected|pr-casting-level}]]lbs.}}{{save=Special}}{{reference=PHB p236}}SpellData=[w:Transmute Metal to Wood,lv:7,sp:10,gp:0,cs:VSM,sph:Elemental-Earth]{{effects=The *transmute metal to wood* spell enables the caster to change an object from metal to wood.}}{{hide1=The volume of metal cannot exceed a maximum weight of 10 pounds per experience level of the priest. Magical objects made of metal are 90% resistant to the spell, and those on the person of a creature receive the creature\'s saving throw as well. Artifacts and relics cannot be transmuted. Note that only a *wish* spell or similar magic can restore a transmuted object to its metallic state. Otherwise, for example, a metal door changed to wood would be forevermore a wooden door.}}{{materials=A metal object to transmute}}'},
+ {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|pr-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.}}{{hide1=Creatures so banished cannot return for at least a day. The spell further affects creatures of differing alignment as shown on the following table:\n**Effects of Unholy Word**\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;Creature\'s Hit Dice or Level\\amplt;/th\\ampgt;\\amplt;th\\ampgt;General\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Attack Move\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Dice\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Spells\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;Less than 4\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Kills\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;4 to 7+\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Paralyzes 1d4 turns](!rounds --target multi|@{selected|token_id}|Paralysis|\\amp#91;[10*1d4]\\amp#93;|-1|Paralysed by the Holy Word|fishing-net)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;8 to 11+\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Slows 2d4 rounds](!rounds --target multi|@{selected|token_id}|Slow_Holy Word|\\amp#91;[2d4]\\amp#93;|-1|Slowed by @{selected|token_name}\'s Holy Word|snail)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-50%\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-4^\\amplt;/td\\ampgt;\\amplt;td\\ampgt;--\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;12 or more\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[Deafens 1d4 rounds](!rounds --target multi|@{selected|token_id}|Deafness_Holy Word|\\amp#91;[1d4]\\amp#93;|-1|Deafened by @{selected|token_name}\'s Holy Word|bleeding-eye)\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-25%\\amplt;/td\\ampgt;\\amplt;td\\ampgt;-2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;50% chance\nof failure\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\n^Slowed creatures attack only on even-numbered rounds until the effect wears off.\nAffected creatures are those within the 30-foot-radius area of effect, which is centered on the priest casting the spell. The side effects are negated for deafened or silenced creatures, but such are still driven off if other-planar.}}'},
+ {name:'Wind-Walk',type:'prspelll7',ct:'10',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWind Walk\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Alteration}}{{sphere=Elemental (Air)}}Specs=[Wind Walk,PRspellL7,1H,Alteration]{{components=V,S,M}}{{range=Touch}}{{time=[[1]] round}}{{duration=[1 hour/level](!rounds --target caster|@{selected|token_id}|Wind-Walk|99|0|Wind walking - only hit by magic or magical weaponry|fluffy-wing --target area|@{selected|token_id}|\\amp#64;{target|Who is Wind Walking with the caster?|token_id}|Wind-Walk|99|0|Wind walking - only hit by magic or magical weaponry|fluffy-wing)}}{{aoe=Caster + 1 person/8 levels}}{{save=None}}{{reference=PHB p236}}SpellData=[w:Wind Walk,lv:7,sp:10,gp:0.1,cs:VSM,sph:Elemental-Air]{{effects=This spell enables the priest (and possibly one or two other persons) to alter the substance of his body to a cloudlike vapor. A magical wind then wafts the priest along at a movement rate of 60, or as slow as 6, as the spellcaster wills.}}{{hide1=The wind walk spell lasts as long as the priest desires, up to a maximum duration of six turns (one hour) per experience level of the caster. For every eight levels of experience the priest has attained, up to 24, he is able to touch another person and carry that person, or those persons, along on the wind walk. Persons wind walking are not invisible, but rather appear misty and translucent. If fully clothed in white, they are 80% likely to be mistaken for clouds, fog, vapors, etc. The priest can regain his physical form as desired, each change to and from vaporous form requiring five rounds. While in vaporous form, the priest and companions are hit only by magic or magical weaponry, though they may be subject to high winds at the DM\'s discretion. No spellcasting is possible in vaporous form.}}{{materials=Fire and holy water.}}'},
+ {name:'Wither',type:'innate-melee|prspelll7',ct:'1',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} casts\nWither\nas a level @{selected|pr-casting-level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Wither,Innate-Melee|PRspellL7,1H,Necromancy]{{components=V,S,M}}{{range=Touch attack}}{{time=[[1]] round}}{{duration=Permanent}}{{aoe=Creature Touched}}ToHitData=[w:Wither,sp:1,sb:0,ty:SPB,r:5,touch:1,msg:A successful hit withers the member or organ touched ceasing to function in 1 round and dropping off into dust in \\lbrak;2d4 turns\\rbrak;\\lpar;!rounds ~~target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who\'s member will wither?\\vbar;token_id}\\vbar;Wither\\vbar;\\amp#91;\\lbrak;10*2d4\\rbrak;\\amp#93;\\vbar;-1\\vbar;Touched limb / member / organ is withering and turning to dust\\vbar;back-pain\\rpar;]{{save=None}}DmgData=[w:Wither,sb:0,SM:0,L:0,msg:A successful hit withers the member or organ touched ceasing to function in 1 round and dropping off into dust in \\lbrak;2d4 turns\\rbrak;\\lpar;!rounds ~~target single\\vbar;\\at;{selected\\vbar;token_id}\\vbar;\\amp#64;{target\\vbar;Who\'s member will wither?\\vbar;token_id}\\vbar;Wither\\vbar;\\amp#91;\\lbrak;10*2d4\\rbrak;\\amp#93;\\vbar;-1\\vbar;Touched limb / member / organ is withering and turning to dust\\vbar;back-pain\\rpar;]{{reference=PHB p234}}SpellData=[w:Wither,lv:7,sp:1,gp:0.1,cs:VSM,sph:Necromantic]{{Use=Take the spell in-hand using *Attk Menu \\gt Change Weapon* or when casting, and attack with it. Called shots attract penalties to hit.}}{{effects=Causes the member or organ touched to cease functioning in one round, dropping off into dust in 2d4 turns. Creatures must be touched for the harmful effect to occur.}}{{materials=A prayer device and unholy water}}'},
+ ]},
+ Powers_DB: {bio:'Powers Database
v7.04 31/03/2024
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:
v7.04 31/03/2024 Added final few powers for last magic items from DMG
v7.03 08/03/2024 Added power for Scarab of Protection Absorb Level Drain
v7.02 04/02/2024 Added more powers for new weapons
v7.01 01/11/2023 Changed way casting-level of powers is specified
v6.30 29/09/2023 Added powers for Chromatic & Metalic Dragons, & Hell Hound breath
v6.29 20/07/2023 Added powers for Jewels and Necklaces
v6.28 07/07/2023 Added powers for Djinn & Rakshasa, and the Symbol spell
v6.27 08/06/2023 Corrected Staff of Curing: Cure Blindness as a power
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:7.05,
+ 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-nosave 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-nosave 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|pr-casting-level}]] turns](!rounds --target-nosave caster|@{selected|token_id}|Shapechange-Power|[[10*@{selected|pr-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:'Bead-of-Curing',type:'power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses \n**Bead of Curing**\non their *Necklace of Prayer Beads*}}Specs=[Bead of Curing,Power,1H,Necromancy]{{splevel=Necromancy}}{{School=Healing}}{{time=[[3]]}}{{Range=Touch}}{{Duration=Permanent}}{{AoE=1 creature}}{{save=None}}{{reference=DMG p175}}SpellData=[w:Bead of Curing,sp:3,cs:M]{{effects=Once per day, cure [blindness](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cure-Blindness-or-Deafness), [disease](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cure-Disease), or [serious wounds](!magic --display-ability @{selected|token_id}|PR-Spells-DB|Cure-Serious-Wounds) (as the appropriate spells)}}'},
+ {name:'Bead-of-Karma',type:'power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses \n**Bead of Karma**\non their *Necklace of Prayer Beads*}}Specs=[Bead of Karma,Power,1H,Alteration]{{splevel=Alteration}}{{Sphere=All}}{{Time=[[3]]}}{{Range=0}}{{Duration=1 spell}}{{AoE=Caster}}{{save=None}}{{reference=DMG p175}}SpellData=[w:Bead of Karma,sp:3,cs:M]{{Use=In order to cast a spell 4 levels higher with respect to range, duration etc., the button in the description below must be used}}{{desc=Once per day, allows the priest to [cast a spell](!magic --cast-spell PR|@{selected|token_id}|[[@{selected|pr-casting-level}+4]]) as if they were four levels higher (with respect to range, duration, etc. - but not any spells of a higher level than the priest can normally cast)}}'},
+ {name:'Bead-of-Summons',type:'power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses \n**Bead of Summons**\non their *Necklace of Prayer Beads*}}Specs=[Bead of Summons,Power,1H,Summoning]{{splevel=Power}}{{Sphere=Summoning}}{{time=[[3]]}}{{Range=0}}{{Duration=Special}}{{AoE=1 deity}}{{save=None}}{{reference=DMG p175}}SpellData=[w:Bead of Summoning,sp:3,cs:M]{{GM info=If the priest summons his deity frivolously, the deity will, at the very least, take the necklace as punishment.}}{{effects=Once per day, calls the priest\'s deity ([90% probability](!\\amp#13;\\amp#47;r 1d100)) to come to him in material form (but it had better be for a good reason!).}}'},
+ {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}}{{use=Click [Recruit](!rounds --target single|@{selected|token_id}|@{target|Which beast to commune with?|token_id}|BM Recruit Animal|99|0|Considers @{selected|casting-name} as not hostile \\amp perhaps a friend|chained-heart|svrod\\clon;[[ceil(@{selected|casting-level}/3)]]) and select the animal, which then prompts for the appropriate save to be made}}{{save=save vs Rod with a +[[ceil(@{selected|casting-level}/3)]] benefit 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|svsar\\clon;+0) and [2d6 rounds](!rounds --removetargetstatus \\amp#64;{target|Who\'s the Victim?|token_id}|Mesmerized) 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:'Black-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Black }}{{title=Dragon Breath}}{{use=Show the [60ft x 5ft blast](!rounds --aoe @{selected|token_id}|bolt|feet|0|60|5|Acid --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) of acid which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d4+@{selected|age|max}]] HP damage (save. vs breath to halve}}{{desc=A black dragon\'s breath weapon is an acidic bolt 60\' long and 5\' wide. Creatures struck by the acid must save versus breath weapon for half damage. The damage done increases with the dragon\'s age: from 2d4+1 to 24d4+12. The damage shown above includes this age-related dice roll}}'},
+ {name:'Black-Dragon-Darkness',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nBlack Dragon Darkness\nas a Power}}{{splevel=Power}}{{school=Alteration}}Specs=[Black Dragon Darkness,Power,1H,Alteration]{{components=V}}{{time=[[1]]}}{{range=[[@{selected|casting-level}*10]] yds}}{{duration=[[@{selected|casting-level}+10]] rounds}}{{aoe=[ @{selected|age|max}0ft. radius (or as cast)](!rounds --aoe @{selected|token_id}|circle|feet|[[@{selected|casting-level}*30]]||@{selected|age|max}0|black||@{selected|token_id}|caster|Darkness|[[@{selected|casting-level}+10]]|-1|Ticking down the duration of darkness|stopwatch)}}{{save=None}}{{reference=PHB p140}}SpellData=[w:Black-Dragon-Darkness,sp:1,cs:V]{{effects=This spell causes total, impenetrable darkness in the area of effect}}'},
+ {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}}{{save=None}}{{Use=Click [Super-Speed](!rounds --aoe @{selected|token_id}|square|feet|180|40||magic||@{selected|token_id}|multi|Haste|15|-1|Hasted, double attacks, move etc|Strong) and then select the creatures to be hasted before pressing the *add status changes* in the chat window}}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:'Blood-Frenzy',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nBlood Frenzy}}{{splevel=Power}}{{school=Alteration}}Specs=[Blood Frenzy,Power,0H,Alteration]{{components=S}}{{time=[[0]]}}{{range=[[0]]}}{{duration=[While smell blood](!rounds --target-nosave caster|@{selected|token_id}|Blood-Frenzy|99|0|Maddened by the smell of blood, can attack at twice the rate|Lightning-helix)}}{{aoe=The Caster}}{{save=None}}SpellData=[w:Blood Frenzy,sp:0]{{effects=A creature maddened by the smell of blood goes into an attacking frenzy, and doubles its rate of attack}}'},
+ {name:'Blue-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Blue }}{{title=Dragon Breath}}{{use=Show the [100ft x 5ft bolt](!rounds --aoe @{selected|token_id}|bolt|feet|0|100|5|Lightning --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) of electricity which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d8+@{selected|age|max}]] HP damage (save. vs breath to halve}}{{desc=A blue dragon\'s breath weapon is a bolt of electricity 100\' long and 5\' wide. Creatures struck by the lightning must save versus breath weapon for half damage. The damage done increases with the dragon\'s age: from 2d8+1 to 24d8+12. The damage shown above includes this age-related dice roll}}'},
+ {name:'Brass-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Brass}}{{title=Dragon Breath}}{{use=**Searing Hot Air:** Show the [50ft x 40ft cloud](!rounds --aoe @{selected|token_id}|rectangle|feet|0|50|40|fire --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d4+@{selected|age|max}]] HP damage (save. vs breath to halve).\n**Sleeping Gas:** Show a [70ft x 20ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|70|20|magic --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) of gas, save vs. breath weapon or [Sleep](!rounds --target multi|@{selected|token_id}|Sleep|[[5*@{selected|casting-level}]]|-1|Fallen asleep for a while|sleepy|svbre\\clon;+0) regardless of Hit Dice or level}}{{desc=A brass dragon has two breath weapons: a cone of sleep gas 70\' long, 5\' wide at the dragon\'s mouth, and 20\' wide at its end; or a cloud of blistering desert heat 50\' long, 40\' wide, and 20\' high. Creatures caught in the gas, regardless of Hit Dice or level, must save vs. breath weapon for half.}}'},
+ {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-nosave 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:'Bronze-Dragon-Airy-Water',type:'power',ct:'5',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\n**Airy Water**\nas a Power}}{{splevel=Power}}{{school=Alteration}}Specs=[Airy Water,Power,1H,Alteration]{{components=V}}{{time=[[1]]}}{{range=[[0]]}}{{duration=[[@{selected|casting-level}]] turns}}{{aoe=[ [[10*@{selected|age|max}]]ft radius sphere](!rounds --aoe @{selected|token_id}|circle|feet|0|[[10*@{selected|age|max}]]||light|true --target-nosave caster|@{selected|token_id}|Airy-water-10|[[10*@{selected|casting-level}]]|-1|Ah, room to breathe|aura)}}{{save=None}}{{reference=PHB p165}}SpellData=[w:Airy Water,lv:5,sp:5,gp:0.5,cs:VSM]{{effects=Turns normal liquid, such as water or water-based solutions, into a less dense, breathable substance.}}'},
+ {name:'Bronze-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Bronze}}{{title=Dragon Breath}}{{use=**Lightning Bolt:** Show the [100ft x 5ft bolt](!rounds --aoe @{selected|token_id}|bolt|feet|0|100|5|lightning --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d8+@{selected|age|max}]] HP damage (save. vs breath to halve).\n**Repulsion Gas:** Show a [20ft x 30ft](!rounds --aoe @{selected|token_id}|rectangle|feet|0|20|30|acid --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) x 30ft high cloud of gas, save vs. breath weapon or [flee](!rounds --target multi|@{selected|token_id}|Flee|[[2*@{selected|age|max}+1d6]]|-1|Fleeing away from the dragon|screaming|svbre\\clon;+0) away from the bronze dragon for the duration}}{{desc=A bronze dragon has two breath weapons: a stroke of lightning 100\' long and 5\' side or a cloud of repulsion gas 20\' long, 30\' wide, and 30\' high. Creatures caught in the gas must save vs. breath weapon or move away from the dragon for two minutes per age level of the dragon, plus 1-6 minutes. Creature caught in the lightning take damage, save vs. breath weapon for half.}}'},
+ {name:'Change-to-Crocodile',type:'power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} Polymorphs into a Crocodile}}{{splevel=Power}}{{school=Alteration}}Specs=[Polymorph-Self,Power,0H,Alteration]{{components=V}}{{time=[[4]]}}{{range=[[0]]}}{{duration=[Up to 1 hour](!rounds --target-nosave caster|@{selected|token_id}|Polymorph-Self|[[2*@{selected|mu-casting-level}]]|-1|Polymorphed to Crocodile - stats don\'t change|strong)}}{{aoe=The caster}}{{save=None}}SpellData=[w:Polymorph to Crocodile,sp:4,cs:V]{{effects=Assume the form of a Crocodile. Gains physical mode of locomotion and breathing. Does not give attack, magic, special movement, etc. Equipment does ***not*** meld into new form. Retains all mental abilities, including spell use. Can change form once then needs a Short or Long rest. Retains own HP, attack rolls, and saving throws. Can end the spell at any time; voluntarily returning to own form and ending the spell, regains [1d12](!\\amp#13;\\amp#47;r 1d12) hit points. Will return to his own form when slain or dispelled, but no hit points are restored in these cases.}}'},
+ {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-nosave caster|@{selected|token_id}|Chariot of Sustarre|720|-1|You have a flaming flying chariot, move 24, FL 48|overdrive)}}{{aoe=Special}}{{save=Special 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|pr-casting-level}]] hours}}{{aoe=[[1]] creature}}{{save=Negates}}{{reference=*The Complete Priest\'s Handbook*, Powers}}{{Use=Click [Make a Suggestion](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select suggestable target|token_id}|Suggestion|[[60+(60*@{selected|pr-casting-level})]]|-1|Agrees with the Wizard\'s Suggestion and getting on with it|chained-heart|svspe\\clon;+0) and select the target, which will then be asked to make a saving throw}}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:'Charm-Reptiles',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses \n**Charm Reptile**\nas a Power}}{{splevel=Power}}{{school=Enchantment/Charm}}{{sphere=Animal}}Specs=[Charm-Reptile,Power,1H,Enchantment-Charm]{{components=V}}{{time=[[1]]}}{{range=[80 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|160||magic)}}{{duration=Special - at least 1 day}}{{aoe=Charms [[1]] reptile or reptilian creature}}{{save=Negates}}{{reference=PHB p203}}{{Use=Click [Charms](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select new friend|token_id}|Charm-P-or-M|99|0|Charmed|chained-heart|svspe\\clon;+0), then select the target which will then prompt a saving throw}}SpellData=[w:Charm-Reptile,sp:1,cs:V,sph:Animal]{{effects=Charm one reptile or reptilian creature. Save vs. spell or believes caster is trusted friend and ally to be protected.}}'},
+ {name:'Cloud-Walk',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Cloud Walk**\nas a Power}}Specs=[Cloud-Walk,Power,1H,Alteration]{{Speed=[[1]]}}{{Range=0}}SpellData=[w:Cloud Walk,sp:1,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=This allows the caster to tread on clouds or fog as though they were solid ground. The ability functions continuously, but can be negated or resumed at will.}}'},
+ {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}}{{Use=[Control them](!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) to select each undead in turn and make a *turn undead* check as described below}}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:'Copper-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Copper}}{{title=Dragon Breath}}{{use=**Spurt of Acid:** Show the [70ft x 5ft spurt](!rounds --aoe @{selected|token_id}|bolt|feet|0|70|5|acid --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d6+@{selected|age|max}]] HP damage (save. vs breath to halve).\n**Slow Gas:** Show a [20ft x 30ft](!rounds --aoe @{selected|token_id}|rectangle|feet|0|30|20|magic --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) x 30ft high cloud of gas, select [be slowed](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Which creature is slowed?|token_id}|slow|[[3@{selected|age|max}]]|-1|Slowed by the breath of a *Copper Dragon*|snail|svbre\\clon;+0) which will prompt for save vs. breath weapon.}}{{desc=Copper dragon\'s breath is either a cloud of *slow* gas 30\' long, 20\' wide, and 20\' high or a spurt of *acid* 70\' long and 5\' wide. Creatures caught in the gas must save vs. breath weapon or be *slowed* for three minutes per age level of the dragon. Creatures caught in the *acid* take damage, save vs. breath weapon for half.}}'},
+ {name:'Corrupt-Water',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Corrupt Water**\nas a Power}}Specs=[Corrupt Water,Power,1H,Alteration]{{Speed=[[1]]}}{{Range=0}}SpellData=[w:Corrupt Water,sp:1,cs:V]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=For every age category a dragon attains, it can stagnate 10 cubic feet of water (in this case 10 x @{selected|age|max} cu.ft.), making it become still, foul, inert, and unable to support animal life. When this ability is used against potions and elixirs, they become useless if they roll a 15 or better on 1d20.}}'},
+ {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|pr-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:'Croaked-Decree',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nCroaked Decree}}{{splevel=Power}}{{school=Creature}}{{sphere=Combat}}Specs=[Croaked Decree,Power,0H,Creature]{{components=V}}{{time=[[1]]}}{{range=0}}{{duration=Next attack}}{{aoe=[60 Feet](!rounds --aoe @{selected|token_id}|circle|feet|0|30|30|dark|true --target multi|@{selected|token_id}|Croaked Decree|99|0|Gain advantage on next attack|all-for-one)}}{{Use=Use the Area of Effect button, that will display the area and prompt to select all bullywug in the area{{save=None}}SpellData=[w:Croaked Decree,sp:1,cs:V]{{effects=The royal makes a loud pronouncement. Each bullywug within 60 feet of the royal that can hear the pronouncement has advantage on its next attack roll.}}'},
+ {name:'Cure-Blindness',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Staff of Curing\nCure Blindness}}{{splevel=Magic Item Power}}{{school=Necromancy}}{{sphere=Healing}}Specs=[Cure Blindness,Power,1H,Necromancy]{{components=V,M}}{{time=[[10]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 Creature}}{{save=None}}{{reference=DMG p154}}SpellData=[w:Cure Blindness,sp:10,cs:VM]{{effects=By touching the creature afflicted, the priest employing the spell can permanently cure some forms of blindness. This spell does not restore or repair visual organs damaged by injury or disease. Only once per creature per day, and only twice a day in total}}'},
+ {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:'Dancing-Lights',type:'power',ct:'1',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses their Power\nDancing Lights\nas a level @{selected|casting-level} caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Dancing Lights,Power,0H,Alteration]{{components=V, S}}{{time=[[1]]}}{{range=[[[40+(10*@{selected|casting-level})]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[40+(10*@{selected|casting-level})]]||light|true)}}{{duration=[[[2*@{selected|casting-level}]] rounds](!rounds --target-nosave caster|@{selected|token_id}|Dancing-Lights|[[2*@{selected|casting-level}]]|-1|Pretty Dancing Lights!|aura)}}{{aoe=Special}}{{save=None}}{{reference=PHB p133}}SpellData=[w:Dancing-Lights,lv:1,sp:1,gp:0.5,cs:VSM]{{effects=Creates, at the wizard\'s option, from one to four lights that resemble either torches or lanterns (and cast that amount of light), glowing spheres of light (such as evidenced by will-o-wisps), or one faintly glowing, vaguely manlike shape, somewhat similar to that of a creature from the Elemental Plane of Fire.}}{{use=Use the *Duration* button to set a status timer (requires use of Turn Order or DM\'s *Maint Menu* to advance the Round Counter)}}'},
+ {name:'Darkness',type:'power',ct:'4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nDarkness\nas a level @{selected|Casting-Level} caster}}{{splevel=Power}}{{school=Alteration}}{{sphere=Sun}}Specs=[Darkness,Power,0H,Alteration]{{components=V}}{{time=[[4]]}}{{range=[[120]] yards}}{{duration=[[[@{selected|Casting-Level}]] + 6 turns](!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|svspe\\clon;+0)}}{{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)}}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.}}{{use=If cast on a creature, use the *Duration* button then select the creature to cast on to set a status timer and place the effects of blindness on their character sheet. If casting on an area, use the *Area of Effect* button and target the centre of the desired location before *Confirming*.}}'},
+ {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-nosave 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-nosave 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*](!magic --display-ability @{selected|token_id}|PR-Spells-DB|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-Gems-Kind+Number',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Detect Gems, Kind \\amp Number**\nas a Power}}Specs=[Detect-Gems,Power,1H,Divination]{{Speed=[[0]]}}{{Range=0}}SpellData=[w:Detect-Gems,sp:0,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=Some creatures, especially some types of dragon, can detect gems at a distance, even if hidden. Some magic items and special weapons can also convey this power to those wielding them. Quite often this includes the kind and number of gems detected. The area of effect of the detection varies by creature and device - see descriptions of these to determine the full nature of each specific use.}}'},
+ {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-nosave 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-Create-Illusion',type:'power',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Create Illusion}}{{splevel=Djinn Power}}{{school=Illusion/Phantasm}}Specs=[Create Illusion,Power,0H,Alteration]{{components=None}}{{time=[[2]]}}{{range=260 yards}}{{duration=Special}}{{aoe=[Up to 1200 sq. ft.](!rounds --aoe @{selected|token_id}||feet|260|||magic)}}{{save=to disbelieve}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Illusion,sp:2,pd:1]{{effects=A standard Djinn power is to create an illusion with both visible and audible components, once per day. It is the equivalent of *Improved Phantasmal Force* cast at 20th level, but does not require any concentration and persists until touched or magically dispelled.}}'},
+ {name:'Djinni-Create-Metal',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Create Metal}}{{splevel=Djinn Power}}{{school=Alteration}}Specs=[Create Metal,Power,0H,Alteration]{{components=None}}{{time=[[10]]}}{{range=Special}}{{duration=Special}}{{aoe=Up to 100 lbs weight}}{{save=None}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Metal,sp:10,pd:1]{{effects=A standard Djinn power is to create up to 100 lbs weight of metal, once per day. However, this metal only has a short lifespan, which depends on the metal\'s hardness. Gold has about a 24 hour life, whereas steel lasts only one hour}}'},
+ {name:'Djinni-Create-Nutritious-Food',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Create Nutritious Food}}{{splevel=Djinn Power}}{{school=Alteration}}Specs=[Create Nutritious Food,Power,0H,Alteration]{{components=None}}{{time=[[10]]}}{{range=Special}}{{duration=Permanent}}{{aoe=[2d6 Persons](!\\amp#13;\\amp#47;gr 2d6 persons of nutritious food created)}}{{save=None}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Nutritious Food,sp:10,pd:1]{{effects=A standard Djinn power is to *Create Nutritious Food* for 2d6 persons, once per day}}'},
+ {name:'Djinni-Create-Soft-Goods',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Create Soft Goods}}{{splevel=Djinn Power}}{{school=Alteration}}Specs=[Create Soft Goods,Power,0H,Alteration]{{components=None}}{{time=[[10]]}}{{range=Special}}{{duration=Permanent}}{{aoe=Up to 16 cu ft}}{{save=None}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Soft Goods,sp:10,pd:1]{{effects=A standard Djinn power is to create up to 16 cu ft of soft goods (cushions, mats, blankets, tents, etc), once per day}}'},
+ {name:'Djinni-Create-Wine-or-Water',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Create Wine or Water}}{{splevel=Djinn Power}}{{school=Alteration}}Specs=[Create Wine or Water,Power,0H,Alteration]{{components=None}}{{time=[[10]]}}{{range=Special}}{{duration=Permanent}}{{aoe=[2d6 Persons](!\\amp#13;\\amp#47;gr 2d6 persons of either wine or water created)}}{{save=None}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Wine or Water,sp:10,pd:1]{{effects=A standard Djinn power is to *Create Wine or Water* for 2d6 persons, once per day}}'},
+ {name:'Djinni-Create-Wooden-Items',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=CreateWooden Items}}{{splevel=Djinn Power}}{{school=Alteration}}Specs=[Create Wooden Items,Power,0H,Alteration]{{components=None}}{{time=[[10]]}}{{range=Special}}{{duration=Permanent}}{{aoe=Up to 9 cu ft}}{{save=None}}{{reference=AD\\ampD2e Monstrous Manual Djinni}}SpellData=[w:Create Wooden Items,sp:10,pd:1]{{effects=A standard Djinn power is to create up to 9 cu ft of wooden Items (chairs, bed frames, wooden shields, 10ft poles etc), once per day}}'},
+ {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-nosave 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-nosave 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:'Dragon-Fear',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} exudes \n**Dragon Fear**}}Specs=[Dragon Fear,Power,1H,Combat]{{Speed=[[0]]}}{{Range=[[0}]]}SpellData=[w:Dragon Fear,sp:0,cs:S]{{Use=[Show the area](!rounds --aoe @{selected|token_id}|circle|yards|0|[[({ { { {(@{selected|age|max}-4)},{0} }kh1},{1} }kl1)*(@{selected|age|max}-3)*5]]||lightning|true) affected. For those paniced (less than 1HD) [Flee](!rounds --target multi|@{selected|token_id}|Fleeing|\\amp#91;[4d6]\\amp#93;|-1|Its a dragon! Flee in panic!|screaming) with no saving throw for 4d6 rounds., Others in the area of effect must [be afraid](!rounds --target multi|@{selected|token_id}|Dragon-Fear|99|0|Struck with fear while in the area of effect. If leave get GM to remove fear|half-heart|svpet\\clon;[[8-@{selected|age|max}]]) unless they save vs. petrification at [[8-@{selected|age|max}]] (those outside that are of less than 1HD and can see the dragon are also automatically afraid)}}{{desc=Dragons can inspire panic or fear. The mere sight of a young adult or older dragon causes creatures with fewer than 1 Hit Die (as well as all noncarnivorous, nonaggressive creatures with fewer Hit Dice than the dragon) to automatically flee in panic for 4d6 rounds.\nTrained war mounts, organized military units, and single creatures with 1 Hit Die or more, but with fewer Hit Dice than the dragon are not panicked, but they may be stricken with fear if they are within the dragon\'s fear aura. The aura surrounds attacking or charging dragons in the specified radius and in a path along the ground directly beneath a flying dragon whose altitude is 250 feet or less. Creatures not automatically panicked are entitled to saving throws vs. petrification. Creatures failing their saving throws are stricken with fear and fight with a -2 penalty to their attack and damage rolls. The aura increases in size and power based on the age category of the dragon; creatures subjected to the aura receive a saving throw bonus or a penalty as specified on the Dragon Table. All creatures with Hit Dice equal to or greater than those of the dragon are immune to the fear effect.)}}{{desc1=Gem dragons are not as inherently fearsome as other dragons, so saving throws against their fear auras receive bonuses (in this case [[12-@{selected|age|max}]]); the bonuses appear in parenthesis in the Dragon Table.}}'},
+ {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-nosave 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-nosave 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:'Ego-Telepathy',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Intelligent Item\'s\nTelepathy}}{{splevel=Magic Item Power}}{{school=Psionics}}Specs=[Telepathy,Power,0H,Psionics]{{components=None}}{{time=[[0]]}}{{range=Special}}{{duration=Instantaneous}}{{aoe=1 creature}}{{save=Ego battle - see DMG on Intelligent Items}}SpellData=[w:Ego Telepathy,sp:0]{{effects=A psionic power which combines the Telepathic Sciences *Domination, Mindlink,* and *Probe*. It is a power available to intelligent magic items that have *ego* scores such as intelligent swords.\n**Domination:** can project signals from its own mind into the mind of one other person or creature (possibly only its possessor). if dominant on an Ego Battle score, the subject is forced to do nearly anything the wielder of the power wishes. The dominated subject knows what is happening, but they cannot resist the objects will. Commands are given mentally and automatically. The victims abilities are neither diminished nor enhanced by this power. The subject can be forced to use any power or ability he normally can-assuming the psionicist knows about it.\nDomination does not reveal facts or secrets about a victim. As soon as domination is attempted, an ego check is made between the *personality scores* of the item and the character. If the victim wins the domination is not successful: but if the difference is less than 10 points the victim suffers bad headaches if they don\'t comply with the wishes. If dominated, but the victim is later forced to do something completely abhorrent (against their alignment), they can make another ego check at +10 to regain their free will.\n**Mindlink:** Mindlink allows the item to communicate wordlessly with any intelligent creature he can contact (usually the possessor, intelligence 5 or greater on a human scale). This is two-way communication. It is not the same as mind-reading because the psionicist only receives thoughts which the other party wants to send. Language is not a barrier. Distance affects the telepath\'s ability to make contact, but it has no other effect.\n**Probe:** A probe is similar to ESP, but a probe allows the item to dig much deeper into a subjects subconscious. If the subject fails an *ego battle* personality check, then all his memories and knowledge are accessible to the prober-from memories deep below the surface to those still fresh in the subject\'s mind. The information gained is not necessarily true, but it is true as far as the subject knows. The item wielding the power can learn the answer to one question per round. DMs have some discretion in determining this rate. If the questions (or answers) become too complicated, each may take longer than one round to resolve. Telepaths can probe a subject who is conscious, as well as one who resists. A probe can even be carried out in the midst of melee, provided the telepath can get close enough. If a probed wizard or cleric tries casting a spell, the telepath knows both that a spell is being cast and what the general effects of that spell are.}}'},
+ {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 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 multi|@{selected|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:'Freezing-Fog',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Freezing Fog**\nas a Power}}Specs=[Freezing-Fog,Power,1H,Evocation]{{Speed=[[1]]}}{{Range=Undefined}}SpellData=[w:Freezing Fog,sp:1,cs:S]{{Use=On using the power, select the button to show the area of *freezing fog*}}{{desc=This [obscures vision](!rounds --aoe @{selected|token_id}|circle|feet|0|200|200|cold) in a 100\' radius and causes frost to form, creating a thin layer of glare ice on the ground and on all surfaces within the radius.}}'},
+ {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}}{{Use=[Go Gaseous](!rounds --target-nosave 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 multi|@{selected|token_id}|Nauseous-2|99|0|Made nauseous by Ghast stink, 2 penalty to attacks|half-haze|svpoi\\clon;+0) 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 select those in the area which will prompt a save vs. poison and 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:'Glaaar-pat',type:'power',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nGlaaar-pat}}{{splevel=Power}}{{school=Creature}}{{sphere=Combat}}Specs=[Glaaar-pat,Power,0H,Creature]{{components=V}}{{time=[[8]]}}{{range=0}}{{duration=Instantaneous}}{{aoe=[30 Feet](!rounds --aoe @{selected|token_id}|circle|feet|0|30|30|dark|true)}}{{save=Save vs. spell to halve)}}SpellData=[w:Glaaar-pat,sp:8,cs:V]{{effects=The croaker sings a song of marshy doom. Each chosen creature within 30 feet of the croaker that can hear the song must save vs. spell (Wisdom bonus applies), taking [[1d8]] psychic damage on a failed save, or half as much damage on a successful one. A creature that fails this saving throw also has disadvantage on Saving Throws until the end of its next turn.}}'},
+ {name:'Gold-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Copper}}{{title=Dragon Breath}}{{use=**Cone of fire:** Show the [90ft x 30ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|90|20|fire --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter.\n**Chlorine Gas cloud:** Show a [50ft x 40ft](!rounds --aoe @{selected|token_id}|rectangle|feet|0|50|40|acid --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) x 30ft high cloud of gas.\nEither breath weapon does [[(@{selected|age|max}*2)d12+@{selected|age|max}]] HP damage (save. vs breath to halve).}}{{desc=A gold dragon has two breath weapons: a cone of fire 90\' long, 5\' wide at the dragon\'s mouth, and 30\' wide at the end or a cloud of potent chlorine gas 50\' long, 40\' wide and 30\' high. Creatures caught in either effect are entitled to a save versus breath weapon for 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 vs. Petrification}}{{Use=Display area of effect, then click [Petrify Them](!rounds --target multi|@{selected|token_id}|Petrified|99|0|Petrified by Gorgon Breath|sleepy|svpet\\clon;+0) and select all creatures in the area and press *add status changes* which will prompt or the appropriate saving throw}}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:'Green-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Green }}{{title=Dragon Breath}}{{use=Show the [50ft x 40ft cloud](!rounds --aoe @{selected|token_id}|rectangle|feet|0|50|40|acid --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) of chlorine gas which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d6+@{selected|age|max}]] HP damage (save. vs breath to halve}}{{desc=A green dragon\'s breath weapon is a cloud of poisonous chlorine gas that is 50\' long, 40\' wide, and 30 feet high. Creatures within the cloud may save versus breath weapon for half damage. The damage done increases with the dragon\'s age: from 2d6+1 to 24d6+12. The damage shown above includes this age-related dice roll}}'},
+ {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=vs. poison at +2 bonus}}{{damage=Click [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|svpoi\\clon;+2) which will prompt for a target and then a saving throw with the appropriate bonus applied}}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:'Hell-Hound-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=Hell Hound Breath}}{{use=**Fire Breath:** Show the [10yrd bolt of fire](!rounds --aoe @{selected|token_id}|bolt|yards|0|10|1|fire) aimed at one creature up to 10 yards away. Then do [[@{selected|hitdice]] HP damage (save. vs breath to halve).}}{{desc=Hell hounds attack first by breathing fire at an opponent up to 10 yards away. The fire causes 1 point of damage for each of the hell hound\'s Hit Dice. A successful saving throw vs. breath weapon cuts the damage in half. The hell hound then attacks with its teeth. The hell hound can continue to exhale flame while biting: if the hell hound rolls a natural 20 on its attack roll, it grabs a victim in its jaws and breathes fire on the victim in the same round.}}'},
+ {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}}{{Use=Click [Hide in Shadows](!rounds --target-nosave caster|@{selected|token_id}|Hide-in-Shadow|99|0|Hiding in Shadows, DM determine success, chance @{selected|hst}pct.|ninja-mask) to set a status on the character attempting to hide. The DM can cancel it at any time using *maint menu \\gt edit token*}}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|svpar\\clon;+0) or [1d6 turns](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who\'s the Victim?|token_id}|Hypnotised|\\amp#91;[10\\amp#42;1d6]\\amp#93;|-1|Hypnotised, do whatever they want|chained-heart|svpar\\clon;+0)}}{{aoe=[[1]] creature}}{{save=vs. paralysation negates}}{{Use=Click appropriate *duration* button which will ask for target and then prompt for a saving throw}}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 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:'Ice-Walking',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Ice Walking**\nas a Power}}Specs=[Ice-Walking,Power,1H,Alteration]{{Speed=[[1]]}}{{Range=0}}SpellData=[w:Ice Walking,sp:1,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=Allows the creature to walk across ice as easily as easily as creatures walk across flat, dry ground.}}'},
+ {name:'Improve-Gem',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} attempts to\n**Improve a Gem**\nusing a *Jewel of Flawlessness*}}Specs=[Improve Gem,Power,1H,Alteration]{{Speed=[[10]]}}{{Range=0}}{{Duration=Permanent}}{{Area of Effect=Jewels in same container with *Jewel of Flawlessness*}}{{save=None}}{{reference=DMG p173}}SpellData=[w:Improve Gem,sp:10,cs:M]{{desc=When a jewel of flawlessness is placed with other gems, it doubles the likelihood of their being more valuable (i.e., the chance for each stone going up in value increases from 10% to 20%). The jewel has from 10-100 facets, and whenever a gem increases in value because of the magic of the jewel of flawlessness (a roll of 2 on d10), one of these facets disappears. When all are gone, the jewel is a spherical stone that has no value.\nValue 1 = $[[1]]}}{{Need to Roll=2}}{{Improvement Roll=[[1d10]]}}{{Result=Need to Roll\\gt=Improvement Roll}}{{successcmd=!magic ~~mi-charges @{selected|token_id}¦-[[$[[1]]-1]]¦Jewel-of-Flawlessness¦¦charged}}'},
+ {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-nosave 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|pr-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}}{{Use=Click the *area of effect* button then click [Frighten them](!rounds --target multi|@{selected|token_id}|Inspire-Fear|[[@{selected|pr-casting-level}]]|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming|svspe\\clon;+0) and select all the creatures in the area. The press *add status changes* in the chat window, which will prompt for appropriate saving throws}}{{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:'Iron-Statue-Whirl-Attack',type:'power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nWhirl Attack}}{{splevel=Power}}{{school=Alteration}}Specs=[Whirl-Attack,Power,0H,Alteration]{{components=S}}{{time=[[5]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[10ft radius](!rounds --aoe @{selected|token_id}|circle|feet|0|20|20|lightning|true --target-nosave caster|@{selected|token_id}|Whirl Attack Recharge|\\amp#91;[4+1d2]\\amp#93;|-1|Whirl Attack is recharging|stopwatch)}}{{save=vs. Dexterity-3 to halve damage}}{{damage=[3+3d10](!\\amp#13;\\amp#47;gr 3+3d10 hp damage, save to halve)}}SpellData=[w:Whirl Attack,sp:5,]{{effects=The top of the Living Iron Statue starts whirling, with its deadly blade flashing. All chosen creatures within 10ft of the statue take 3d10+3HP damage, save vs. Dexterity-3 to halve damage. Ability recharges in 5 to 6 rounds}}{{use=Use the Area of Effect button to show which creatures are possible targets, and also set a recharging timer, putting a stopwatch on the token: when it disappears, this power can be used again.}}'},
+ {name:'Jaws-of-Semuanya',type:'power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nJaws of Semuanya}}{{splevel=Power}}{{school=Creature}}{{sphere=Combat}}Specs=[Jaws of Semuanya,Power,0H,Creature]{{components=S}}{{time=[[5]]}}{{range=[60 Feet](!rounds --aoe @{selected|token_id}|circle|feet|0|60|60|dark|true --target-nosave caster|@{selected|token_id}|Jaws recharging|5|-1|The jaws are recharging|stopwatch)}}{{duration=Instantaneous}}{{aoe=1 creature.}}{{save=save vs. spell or suffer [4d6 and Fear](!rounds --target single|@{selected|token_id}|\\amp#64;{target|The Jaws of Semuanya bite who?|token_id}|Fear of the Jaws|2|-1|Running in fear from the Jaws|screaming\\amp#13;\\amp#47;gmroll 4d6)}}SpellData=[w:Jaws of Semuanya,sp:5,cs:VS]{{effects=The caster invokes the primal magic of Semuanya, summoning a spectral maw around a target it can see within 60 feet of it. The target must save vs. spell, taking 4d6 piercing damage on a failed save, or half as much damage on a successful one. A creature that fails this saving throw is also frightened until the end of its next turn.}}{{desc=**Use**\nShow the Area of Effect using the button (the AoE will appear and a status marker be placed on the caster), and then a single chosen creature in the area shown must make a save vs. spell. If fails, select the Damage button. The power cannot be used again until the status marker disappears.}}'},
+ {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}}{{Use=Display the *area of effect* then click [Frighten them](!rounds --target multi|@{selected|token_id}|Fear|[[@{selected|casting-level}]]|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming|svspe\\clon;+0) and select all within the area, then press *add status changes* in the chat window to prompt for saving throws}}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}}{{use=[Levitate](!rounds --target caster-nosave|@{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}}{{use=[Light-em-up!](!rounds --target-nosave 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 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 damage](!rounds --target-nosave caster|@{selected|token_id}|Timer|2|-1|Counting down until next Lava Blob|stopwatch\\amp#13;\\amp#47;gmroll 1d6 heat damage, no saving throw) once every 3 rounds.}}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, which will also set a timer to count down for the next blob}}'},
+ {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|pr-casting-level}]] 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|pr-casting-level}]] 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-nosave 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]{{effects=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:'Levitate-Self',type:'power',ct:'2',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} uses their Power\nLevitate\nas a level @{selected|casting-level} caster}}{{splevel=Power}}{{school=Alteration}}Specs=[Levitate,Power,0H,Alteration]{{components=V, S}}{{time=[[2]]}}{{range=[[20*@{selected|casting-level}]] yds}}{{duration=[[[@{selected|casting-level}]] turns](!rounds --target-nosave caster|@{selected|token_id}|Levitate|[[10*@{selected|casting-level}]]|-1|Levitating vertical not horizontal, minuses on missile fire|fluffy-wing)}}{{aoe=Self}}{{save=None}}{{reference=PHB p143}}SpellData=[w:Levitate,lv:2,sp:2,gp:1,cs:VSM]{{effects=Can place it upon his person only, subject to a maximum weight limit of [[100*@{selected|casting-level}]] pounds. Can move vertically up or down at a movement rate of [[2]] per round.}}{{materials=Either a small leather loop or a piece of golden wire bent into a cup shape with a long shank on one end, costing 1gp}}{{use=Select the *Duration* button to add a status timer (requires use of Turn Order or DM\'s *Maint Menu* to advance the Round Counter)}}'},
+ {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 multi|@{selected|token_id}|Lich Fear|\\amp#91;[5d4]\\amp#93;|-1|Fleeing at maximum move away from the Lich!|screaming|svspe\\clon;+0)}}{{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 *all* creatures in line of sight with less than 5HD, before clicking the *add status changes* button in the chat window which will then prompt for saving throws}}'},
+ {name:'Light-of-Sekolah',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nLight of Sekolah}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Light of Sekolah,Power,0H,Enchantment-Charm]{{components=S}}{{time=[[10]]}}{{range=[[0]]}}{{duration=[1 round](!rounds --target multi|@{selected|token_id}|Light of Sekolah|2|-1|Charmed by the pretty light|chained-heart|svspe\\clon;+0)}}{{aoe=All creatures within [30 foot radius](!rounds --aoe @{selected|token_id}|circle|yards|0|10|10|light|true)}}{{save=vs. Spell}}SpellData=[w:Light of Sekolah,sp:10]{{effects=The deep diver pulses magical light from its lure. Any creature within 30 feet of the deep diver that can see the light must succeed on a DC 11 Wisdom saving throw or be charmed until the end of its next turn. A creature charmed in this way is incapacitated as it stares at the light.}}{{use=Use the *Area of Effect* button to show which creatures can be affected. Then use the *duration* button and select *all* creatures in the area before pressing the *add status changes* button in the chat window, which will prompt for saving throws and set a status timer for those that fail (requires use of Turn Order or DM\'s *Maint Menu* to advance the Round Counter).}}'},
+ {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:'Luck-Bonus',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses\n**Luck Bonus**\nas a Power}}Specs=[Luck Bonus,Power,1H,Abjuration]{{Speed=[[1]]}}{{Range=[[0}]]}}SpellData=[w:Luck Bonus,sp:1,cs:S]{{Use=Select the relevant button below, depending on who holds the luck gem}}{{desc=The dragon can cast the *luck bonus* on a gem it holds itself, or on one given to another.}}{{desc1=[Held by dragon](!rounds --movable-aoe @{selected|token_id}|Circle|feet|0|[[10*@{selected|age|max}]]||light|true|@{selected|token_id}|multi|luck-bonus|[[60*((3*@{selected|age|max})+1d3)]]|-1|Gets +1 on all saving throws and attribute checks etc|strong) luck for *good* creatures of +1 on saves \\amp similar rolls extends to 10ft radius per age category of the dragon}}{{desc2=[Held by another](!rounds --target-nosave single|@{selected|token_id}|@#64;{target|Who becomes lucky?|token_id}|luck-bonus|[[60*((3*@{selected|age|max})+1d3)]]|-1|Gets +1 on all saving throws and attribute checks etc|strong) only applies a *luck bonus* to that individual if they are of a *good* alignment}}'},
+ {name:'Maw-of-Sekolah-Feed',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nFeed}}{{splevel=Power}}{{school=Combat}}Specs=[Feed,Power,0H,Combat]{{components=None}}{{time=[[0]]}}{{range=}}{{duration=Instantanious}}{{aoe=Chosen creatures within [60 foot radius](!rounds --aoe @{selected|token_id}|circle|feet|0|60|60|Lightning|true)}}{{save=vs. Spell}}SpellData=[w:Feed,sp:0]{{effects=The ferocious spirit of Sekolah flashes through the water, tearing through the foes of the maw of Sekolah. Each creature of the maw’s choosing within 60 feet of it must make a saving throw against a *Breath Weapon*, taking [[2d6]] slashing damage on a failed save, or half as much damage on a successful one.}}{{use=Use the *Area of Effect* button to show which creatures can be affected.}}'},
+ {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-nosave 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 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\\amp#13;\\amp#47;gmroll 1d4+1 choking damage, save negates) 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 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}}{{use=[Move Silently](!rounds --target-nosave 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:'Mud-Mephit-Breath',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nMud Breath}}{{splevel=Power}}{{school=Evocation}}Specs=[Mud-Breath,Power,0H,Evocation]{{components=V}}{{time=[[0]]}}{{range=[[5]] feet}}{{duration=[6 rounds](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Select who to cover in mud|token_id}|Mud Breath|6|-1|Pinned down by mud, make Save vs. Breath each round to break free|back-pain|svbre\\clon;+0)}}{{aoe=1 creature}}{{save=vs. Breath to escape}}SpellData=[w:Mud Breath,sp:0]{{effects=The mephit belches viscid mud onto one creature within 5 feet of it. If the target is Medium or smaller, it must save vs. Breath Weapon or be restrained for 6 rounds. A creature can repeat the saving throw at the end of each of its turns, ending the effect on itself on a success.}}{{use=Use the *Duration* button then select the creature to cast on to set a status timer and place the effects on their character sheet (requires use of Turn Order or DM\'s *Maint Menu* to advance the Round Counter). The Player can then make a saving throw each round. If successful, the DM can use the [Edit Selected Tokens] button on the *Maint Menu* to remove the status timer. The Mephit should only use every 6 rounds, but the system does not impose this.}}'},
+ {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}}{{Use=Click [Paralyse with Fear](!rounds --target multi|@{selected|token_id}|Mummy-fear|\\amp#91;[1d4]\\amp#93;|-1|Petrified! Oh Mummy!|screaming|svspe\\clon;+(f(#/6))) then select ***all*** victims in line of sight before pressing the *add status changes* button in the chat window which will then prompt for saving throws (manually add +2 bonus for *human* saving throws)}}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}}{{use=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}}{{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}}{{use=Click [Paralyse](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who is the victim?|token_id}|Paralyse|\\amp#91;[\\amp#63;{Duration?|1d4}]\\amp#93;|-1|Paralysed|fishing-net|svpar\\clon;+0) and then select the victim which will then prompt for a saving throw}}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|svpet\\clon;+0)}}{{aoe=When meet gaze, e.g. surprised, if doing attack etc}}{{save=vs. Petrification Negates}}{{reference=DMG p64}}{{Use=Click the *duration* button then select the victim, which will then prompt for a saving throw}}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.}}{{hide1=Characters 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:'Plummet',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Plummet**\nas an attack}}Specs=[Plummet,Power,1H,Combat]{{Speed=[[0]]}}{{Range=0}}SpellData=[w:Plummet,sp:0,cs:S]{{Use=Specify use of the power during initiative, and then use it during the round to display its description. Use *bite attacks* for each victim to check if they are crushed, doing damage, then the crushed player must save vs. petrification to see if pinned. If pinned use the [pinned] button to mark the victim}}{{desc=If the DM chooses to allow plummets, an airborne dragon, or a dragon jumping and descending from at least 30 feet above a target, can land on a victim. The dragon crushes and pins opponents using its claws and tail, inflicting damage equal to its bite. The dragon can crush as many creatures as its combat modifier / age value, in this case [[@{selected|age|max}]]. The dragon rolls a separate attack against each creature affected (use the *bite* attack). Creatures that are missed are assumed to have escaped. Creatures that are crushed must roll successful saving throws vs. petrification or be [pinned](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is successfully pinned?|token_id}|Pinned|99|0|Pinned by a dragon and taking crushing damage equal to bite damage|fishing-net) under the dragon, automatically suffering crushing damage during the next round unless the dragon moves off them. If the dragon chooses to maintain the pin, the victims must roll successful saving throws vs. petrification to get free. The dragon\'s combat modifier of [[@{selected|strengthdmg}]] applies as a penalty to all saving throw vs. the crush. A dragon cannot take any other actions when plummeting or pinning.}}'},
+ {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:'Produce-Flame',type:'innate-ranged|power',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nProduce Flame\nas a level @{selected|Casting-Level} caster}}Specs=[Produce-Flame,Innate-Ranged|Power,1H,Alteration]{{splevel=Power}}{{school=Alteration}}{{sphere=Elemental (Fire)}}WeapData=[c:0,rc:uncharged,on:!rounds --target-nosave caster|@{selected|token_id}|Produce Flame|@{selected|casting-level}|-1|Producing flaming spheres to hurl|three-leaves,off:!rounds --removetargetstatus @{selected|token_id}|Producce Flame]{{components=None}}ToHitData=[w:Produce Flame,+:0,t:grenade,sb:0,db:1,c:0,sp:5,rc:uncharged,touch:0]{{time=[[5]]}}AmmoData=[w:Produce Flame,t:grenade,sb:0,sm:1+1d4,L:1+1d4,c:0,rc:uncharged,ru:1]{{range=[[40]] yards}}RangeData=[w:Produce Flame,t:Produce-Flame,r:4]{{duration=[[@{selected|Casting-Level}]] rounds}}{{aoe=3ft diameter pool of fire when thrown}}{{save=None}}{{reference=PHB p206}}{{Use=Take the spell in-hand by using *Attk menu \\gt Change Weapon* or by casting it and then *Changing Weapon*, then attack with it as a ranged weapon}}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.}}'},
+ {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-nosave 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}}{{Use=Show the *area of effect* the click [Frighten them](!rounds --target multi|@{selected|token_id}|Fear|3|-1|Frightened, flee at fastest rate from @{selected|Casting-name}|screaming|svspe\\clon;+0) and select all the creatures in the area of effect before pressing *add status changes* in the chat window which will then prompt for saving throws}}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}}{{Use=[Rage!](!rounds --target-nosave 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:'Rakshasa-Illusion',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} uses\nRakshasa Illusion}}{{splevel=Power}}{{school=Innate Ability}}Specs=[Rakshasa Illusion,Power,0H,Innate Ability]{{components=None}}{{time=[[0]]}}{{range=Line of sight}}{{duration=Terminates if Rakshasa attacks}}{{aoe=[1 creature](!rounds --target single|@{selected|token_id|\\amp#64;{target|Who is fooled by the Rakshasa\'s illusion?|token_id}|Some Effect|99|0|Some sort of effect - not sure what|spanner)}}{{save=Disbelieve as per *illusion*}}{{use=Use the Area of Effect button to target and mark the victim the Rakshasa has selected}}SpellData=[w:Rakshasa Illusion,sp:0]{{effects=Rakshasas savor fresh human meat and use illusions to get it. They have a limited form of *ESP* which allows them to disguise themselves as someone the victim trusts; the rakshasa uses this illusion as a lure and strikes when the victim is most unprepared. The rakshasa must drop the illusion when it attacks.}}'},
+ {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|level-class1}/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:'Red-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Red }}{{title=Dragon Breath}}{{use=Show the [90ft x 30ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|90|30|Fire --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d10+@{selected|age|max}]] HP damage (save. vs breath to halve}}{{desc=A red dragon\'s breath weapon is a searing cone of fire 90\' long, 5\' wide at the dragon\'s mouth and 30\' at the base. Creatures struck by the flames must save versus breath weapon for half damage. The damage done increases with the dragon\'s age: from 2d10+1 to 24d10+12. The damage shown above includes this age-related dice roll}}'},
+ {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)}}{{use=Either [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-nosave 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:'Rend-the-Field',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nRend the Field}}{{splevel=Power}}{{school=Creature}}{{sphere=Combat}}Specs=[Rend the Field,Power,0H,Creature]{{components=S}}{{time=[[1]]}}{{range=0}}{{duration=Instantaneous}}{{aoe=[10 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|10|10|red|true --target-nosave caster|@{selected|token_id}|Rend the Field|5|-1|Rending is recharging|grab)}}{{save=vs Paralysation to negate}}{{reference=PHB p206}}SpellData=[w:Rend the Field,sp:1,cs:S]{{effects=The render makes a claw attack against each creature of its choice within 10 feet of it. A creature hit by this attack must succeed on a Paralysation saving throw or be knocked prone.}}{{desc=**Use**\nShow the Area of Effect using the button (the AoE will appear and a status marker be placed on the caster), and then do a claw attack on each chosen creature in the area shown (no damage). If hit, that creature must do a save vs. Paralysation or be knocked prone, needing to spend the next round as a prone opponent getting up. The power cannot be used again until the status marker disappears.}}'},
+ {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-nosave 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-nosave 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}}{{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}}{{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:'Rooooo-glog',type:'power',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their power\nRooooo-glog}}{{splevel=Power}}{{school=Creature}}{{sphere=Combat}}Specs=[Rooooo-glog,Power,0H,Creature]{{components=V}}{{time=[[8]]}}{{range=0}}{{duration=1 turn}}{{aoe=[30 Feet](!rounds --aoe @{selected|token_id}|circle|feet|0|30|30|dark|true --target multi|@{selected|token_id}|Rooooo-glog|10|-1|Boosted by 10 temporary HP by the Croaker\'s song|strong)}}{{use=Select the *area of effect* button then select all the *bullywug* in the area before pressing *add status changes* button in the chat window}}{{save=None}}SpellData=[w:Rooooo-glog,sp:8,cs:V]{{effects=The croaker sings an ode to an elder froghemoth. Each bullywug within 30 feet of the croaker that can hear the song gains 10 temporary hit points.}}'},
+ {name:'Scarab-Protect-Absorb',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses the\nAbsorb Level Drain\nPower of their\nScarab of Protection}}{{splevel=Power}}{{school=Abjuration}}Specs=[Absorb-Level-Drain,Power,0H,Abjuration]{{components=M}}{{time=[[0]]}}{{range=[[0]]}}{{duration=Instantanious}}{{aoe=Caster}}{{save=None}}SpellData=[w:Scarab Protect Absorb,sp:0]{{effects=The *scarab of protection* can absorb up to 12 level-draining attacks (two level drains count as two absorbings), *death touches, death rays,* or *fingers of death*. However, upon absorbing 12 such attacks the scarab turns to powder - totally destroyed.}}'},
+ {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-nosave 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:'Shark-Telepathy',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nShark Telepathy}}{{splevel=Power}}{{school=Enchantment/Charm}}Specs=[Telepathy,Power,0H,Enchantment-Charm]{{components=S}}{{time=[[0]]}}{{range=[[120]] feet}}{{duration=[While concentrate](!rounds --target-nosave single|@{selected|token_id}|\\amp#64;{target|Select which shark to control|token_id}|Shark Telepathy|99|0|Controlled by @{selected|token_name}|chained-heart)}}{{aoe=1 shark within [120 feet](!rounds --aoe @{selected|token_id}|circle|yards|0|40|40|magic|true)}}{{save=None}}SpellData=[w:Shark-Telepathy,sp:0]{{effects=The deep diver can magically command any shark within 120 feet of it, using a limited telepathy.}}'},
+ {name:'Silver-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=Silver}}{{title=Dragon Breath}}{{use=**Cone of Cold:** Show the [80ft x 30ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|80|30|cold --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) which also sets the recovery counter. Then do [[(@{selected|age|max}*2)d10+@{selected|age|max}]] HP damage (save. vs breath to halve).\n**Paralysation Gas:** Show a [50ft x 40ft](!rounds --aoe @{selected|token_id}|rectangle|feet|0|50|40|magic||@{selected|token_id}|multi|paralysed|99|0|Paralysed by the breath of a *Silver Dragon*|padlock|svbre\\clon;+0 --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) x 20ft high cloud of gas, select all creatures in the area and press the *add status changes* button in the chat window which will then prompt for saving throws vs. breath}}{{desc=A silver dragon has two breath weapons: a cone of cold 80\' long, 5\' wide at the dragon\'s mouth, and 30\' wide at the end or a cloud of paralyzation gas 50\' long, 40\' wide, and 20\' high. Creatures caught in the cold are allowed a save versus breath weapon for half damage.Creatures caught in the *cold* take damage, save vs. breath weapon for half.}}'},
+ {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-nosave 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}}{{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|svpoi\\clon;+0)}}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:'Snatch',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Snatch**\nas an attack}}Specs=[Snatch,Power,1H,Combat]{{Speed=[[0]]}}{{Range=0}}SpellData=[w:Snatch,sp:0,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=Only young adult and older dragons can snatch. This occurs when a flying dragon dives and attempts to grab a creature in one of its claws. A creature struck by this method is taken into the air. There is a 50% chance that a snatched creature has its arms pinned, and therefore cannot physically attack the dragon. Snatched creatures are sometimes taken to great heights and dropped. The snatched creature can be squeezed in the claw for automatic claw damage each round, or transferred to the dragon\'s mouth (the transfer requires a successful attack roll). If the transfer succeeds, the victim automatically suffers bite damage each round; if it fails, the victim is dropped. Dragons of age *old* and older can carry a victim in each claw, and they can try to snatch two victims at once. *Wyrms* and *great wyrms* can carry three victims, but one of the first two snatched must be transferred from claw to mouth before the third can be snatched.\nA dragon can snatch creatures two or more size categories smaller than itself. For example, a dragon that is 45\' long is a Gargantuan creature, so the biggest creature it can snatch is a Large one (12\' long).}}'},
+ {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|pr-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:'Sound-Imitation',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Sound Imitation**\nas a Power}}Specs=[Sound-Imitation,Power,1H,Illusion]{{Speed=[[1]]}}{{Range=0}}SpellData=[w:Sound Imitation,sp:1,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=This creature can imitate any sound it has previously heard, but can only imitate a voice if it can speak a language it knows. This capability is very useful when combined with *Ventriloquism*}}'},
+ {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}}{{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](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who is the victim?|token_id}|Paralysed|\\amp#91;[10\\amp#42;8d4]\\amp#93;|-10|Paralysed by a spectator guardian beholder-kin|fishing-net|svpar\\clon;+0) rounds}}{{aoe=1 Creature}}{{save=Negates}}{{use=Use the *duration* button to select the victim and prompt for a saving throw}}{{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}}{{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}}{{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:'Stall',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Stall**\nas an attack}}Specs=[Stall,Power,1H,Combat]{{Speed=[[0]]}}{{Range=0}}SpellData=[w:Stall,sp:0,cs:S]{{Use=Just specify use of the power during initiative, and then use it during the round to display its description}}{{desc=Any dragon flying near the ground can halt its forward motion and hover for one round; it must land immediately thereafter. Once stopped, the dragon can attack with its bite and all four legs. It can use its breath weapon instead, but this rarely happens since dragons can breathe on the wing. If a dragon stalls in an area with lots of trees or loose earth, the draft from its wings creates a dust cloud with the [same radius](!rounds --aoe @{selected|token_id}|circle|yards|0|[[({ { { {(@{selected|age|max}-4)},{0} }kh1},{1} }kl1)*(@{selected|age|max}-3)*5]]||light|true) as its fear aura. Creatures within the cloud are blinded, and no spell casting is possible. The dust lasts for one round.}}'},
+ {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-nosave 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-nosave 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:'Summon-Djinni',type:'power',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} \n**Summons a Djinni**\nas a Power}}Specs=[Summon-Djinni,Power,1H,Conjuration-Summoning]{{Speed=[[1]]}}{{Range=0}}SpellData=[w:Summon-Djinni,sp:1,cs:S]{{Use=The GM should create a *Drag \\amp Drop* Djinni by creating a blank character sheet (with a name and suitable image) and dragging it onto the playing surface to drop a token. Select it and use the *Drag \\amp Drop* dialog that will have appeared in the Chat Window to select the Djinni as a Creature.}}{{desc=The dragon usually asks the djinni to preform some service. Although the djinni serves willingly, the dragon will order it into combat only in extreme circumstances, as the dragon would be dismayed and embarrassed if the djinni were killed.}}'},
+ {name:'Summon-Earth-Elemental',type:'power',ct:'10*1d4',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} \n**Summons Earth Elemental**\nas a Power}}Specs=[Summon-Earth-Elemental,Power,0H,Conjuration-Summoning]{{Speed=1d4 rounds}}{{Range=0}}SpellData=[w:Summon-Earth-Elemental,sp:10*1d4,cs:VM]{{Use=The GM should create a *Drag \\amp Drop* Earth Elemental (see below regards number of hit dice) by creating a blank character sheet (with a name and suitable image) and dragging it onto the playing surface to drop a token. Select it and use the *Drag \\amp Drop* dialog that will have appeared in the Chat Window to select the appropriate Earth Elemental as a Creature.}}{{desc=The user of this power need but utter a single command word, and an earth elemental of 12-Hit-Dice size will come to the summoner if earth is available, an 8-Hit-Dice elemental if rough, unhewn stone is the summoning medium. (An earth elemental cannot be summoned from worked stone, but one can be from mud, clay, or even sand, although one from sand is an eight-dice monster.) The area of summoning for an earth elemental must be at least 4 feet square and have four cubic yards volume. The elemental will appear in 1d4 rounds.}}'},
+ {name:'Sunray',type:'itempower',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|token_name} swings their\nSun Blade\nto create Sunlight}}{{splevel=Power}}{{school=Alteration}}Specs=[Sunray,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-nosave caster|@{selected|token_id}|SunBlade-Daylight|1|1|Spreading daylight +5ft radius/round to 60ft|aura)}}SpellData=[w:Sunray,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:'Symbol-of-Hopelessnes',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Symbol of Hopelessness}}{{splevel=Spell}}{{school=Conjuration Summoning}}Specs=[Symbol of Hopelessness,Power,0H,Conjuration-Summoning]{{components=None}}{{time=[[0]]}}{{range=[60 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|120|120|dark|true)}}{{duration=3d4 turns}}{{aoe=[All creatures viewing symbol](!rounds --target multi|@{selected|token_id}|Symbol-Hopelessness|\\amp#91;[10\\amp#42;3d4]\\amp#93;|-1|Feeling dejected so turn back, surrender, or attack hopelessly|broken-skull|svspe\\clon;+0)}}{{save=vs. spell to negate}}{{use=Show the range of the symbol using the *range* button, then use the *area of effect* button and select all in the range looking at the symbol before pressing *add status changes* in the chat window which will prompt for saving throws}}{{reference=PHB page 236}}SpellData=[w:Symbol of Hopelessness,sp:0,pd:-1]{{effects=Creatures seeing this symbol must turn back in dejection or surrender to capture or attack unless they roll successful saving throws vs. spell. Its effects last for 3d4 turns.}}'},
+ {name:'Symbol-of-Pain',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Symbol of Pain}}{{splevel=Spell}}{{school=Conjuration Summoning}}Specs=[Symbol of Pain,Power,0H,Conjuration-Summoning]{{components=None}}{{time=[[0]]}}{{range=[60 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|120|120|dark|true)}}{{duration=2d10 turns}}{{aoe=[All creatures viewing symbol](!rounds --target multi|@{selected|token_id}|\\amp#64;{target|Who is viewing the symbol?|token_id}|Symbol-Pain|\\amp#91;[10\\amp#42;2d10]\\amp#93;|-1|Wracking pains so attack at -4 penalty and -2 to dexterity checks|broken-skull|svspe\\clon;+0)}}{{save=vs. spell to negate}}{{use=Show the range of the symbol using the *range* button, then use the *area of effect* button and select all in the range looking at the symbol before pressing *add status changes* in the chat window which will prompt for saving throws}}{{reference=PHB page 236}}SpellData=[w:Symbol of Pain,sp:0,pd:-1]{{effects=Creatures seeing this symbol suffer -4 penalties to their attack rolls and -2 penalties to their Dexterity ability scores due to wracking pains. The effects last for 2d10 turns.}}'},
+ {name:'Symbol-of-Pursuasion',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=Symbol of Pursuasion}}{{splevel=Spell}}{{school=Conjuration Summoning}}Specs=[Symbol of Pursuasion,Power,0H,Conjuration-Summoning]{{components=None}}{{time=[[0]]}}{{range=[60 feet](!rounds --aoe @{selected|token_id}|circle|feet|0|120|120|dark|true)}}{{duration=1d20 turns}}{{aoe=[All creatures viewing symbol](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is viewing the symbol?|token_id}|Symbol-Pursuasion|\\amp#91;[10\\amp#42;1d20]\\amp#93;|-1|Become same alignment and fiendly to the priest who cast the symbol|broken-skull)}}{{save=vs. spell to negate}}{{use=Show the range of the symbol using the *range* button, then use the *area of effect* button and select all in the range looking at the symbol before pressing *add status changes* in the chat window which will prompt for saving throws}}{{reference=PHB page 236}}SpellData=[w:Symbol of Pursuasion,sp:0,pd:-1]{{effects=Creatures seeing the symbol become of the same alignment as and friendly to the priest who scribed the symbol for 1d20 turns}}'},
+ {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]]}}{{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)}}{{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)}}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}}{{Use=[See more clearly](!rounds --target-nosave 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}}{{Use=[Grant gills](!rounds --target-nosave 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}}{{Use=[Grant gills](!rounds --target-nosave 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}}{{Use=[Evil radar on](!rounds --target-nosave 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}}{{use=[Good radar on](!rounds --target-nosave 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}}{{Use=Show the *area of effect* then click [Stunning!](!rounds --target multi|@{selected|token_id}|Whelm-Stunned|10|-1|Stunned roll save vs Staves again|fishing-net|svsta\\clon;+0) and select all the foes in the area before pressing *add status changes* in the chat window which will prompt for saving throws}}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:'Whirlpool',type:'power',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|Casting-name} uses their Power\nWhirlpool}}{{splevel=Power}}{{school=Evocation}}Specs=[Whirlpool,Power,0H,Evocation]{{components=V}}{{time=[[10]]}}{{range=[[100]] feet}}{{duration=[6 rounds](!rounds --target-nosave caster|@{selected|token_id}|Whirlpool|6|-1|Created whirlpool lasts while @{selected|token_name} is not incapacitated|dizzy)}}{{aoe=[50ft x 25ft deep](!rounds --aoe @{selected|token_id}|circle|feet|100|50|50|magic)}}{{save=Special}}SpellData=[w:Whirlpool,sp:10]{{effects=The wave shaper targets a body of water at least 50 feet square and 25 feet deep, causing a whirlpool to form in the center of the area. The whirlpool forms a vortex that is 5 feet wide at the base, up to 50 feet wide at the top, 25 feet tall, and lasts for 6 rounds or until the wave shaper is incapacitated. Any creature or object in the water and within 25 feet of the vortex is pulled 10 feet toward it. A creature can swim away from the vortex by succeeding on a DC 14 Strength (Athletics) check.\nWhen a creature enters the vortex for the first time on a turn or starts its turn there, it must make a DC 14 Strength saving throw. On a failed save, the creature takes 9 (2d8) bludgeoning damage and is caught in the vortex until it ends. On a success, the creature takes half damage and isn’t caught in the vortex. A creature caught in the vortex can use its action to try to swim away from the vortex as described above, but it has disadvantage on the Strength (Athletics) check to do so.\nThe first time each turn that an object enters the vortex, the object takes 9 (2d8) bludgeoning damage. This damage occurs each round it remains in the vortex.}}'},
+ {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-nosave 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:'White-Dragon-Breath',type:'',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{prefix=White}}{{title=Dragon Breath}}{{use=Show the [70ft x 25ft cone](!rounds --aoe @{selected|token_id}|cone|feet|0|70|25|Cold --target-nosave caster|@{selected|token_id}|Dragon-Breath|3|-1|Catching breath before breathing again|stopwatch) of frost which also sets the recovery counter. Then do [[(@{selected|age|max})d6+@{selected|age|max}]] HP damage (save. vs breath to halve}}{{desc=A white dragon\'s breath weapon is a come of frost 70\' long, 5\' wide at the dragon\'s mouth, and 25\' wide at the base. Creatures caught in the blast may Save versus Breath Weapon for half damage.The damage done increases with the dragon\'s age: from 1d6+1 to 12d6+12. The damage shown above includes this age-related dice roll}}'},
+ {name:'Wing-Buffet',type:'power',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses \n**Wing Buffet**\nas an attack}}Specs=[Wing Buffet,Power,1H,Combat]{{Speed=[[0]]}}{{Range=0}}SpellData=[w:Wing Buffet,sp:0,cs:S]{{Use=Just specify use of the power during initiative, use it during the round to display its description, and do Claw attacks to assess succes and do damage}}{{desc=Young adult and older dragons can employ their wings in combat; targets must be at the dragon\'s sides. The damage inflicted is the same as a claw attack, and creatures struck must roll their Dexterity or less on 1d20 or be knocked prone.}}'},
+ {name:'Wings-of-Flying-Fly',type:'power',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{title=@{selected|token_name} uses\n**Wings of Flying**\nto fly}}Specs=[Wings of Flying Fly,Power,0H,Alteration]{{Speed=[[3]]}}{{Range=Caster}}SpellData=[w:Wings of Flying Fly,sp:3,cs:VM]{{desc=If the wearer of the *wings of flying* speaks a command word, the cloak will turn into a pair of gigantic bat wings (20-foot span) and empower the wearer to fly as follows:\n2 turns at speed 32\n3 turns at speed 25\n4 turns at speed 18\n6 turns at speed 15\n8 turns at speed 12\nAfter the maximum number of possible turns flying, the wearer must rest for one hour - sitting, lying down, or sleeping. Shorter periods of flight do not require full rest, but only relative quiet such as slow walking for one hour. Any flight of less than one turn\'s duration does not require any rest.}}'},
+ {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:'3.500',
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGM Release Notes v3.500'
+ +'
'
+ +''
+ +'
RPGMaster Release Notes
'
+ +'
for version 3.5.0
'
+ +'
'
+ +'
v3.5 Release Notes
'
+ +'
Saving Throw Mods Table
'
+ +'
Many spells and powers as well as magic items have an effect on saving throws and attribute checks. To date, all such effects have been lumped into a single "effect of magic" number with no further explanation when reviewing how saves and checks are calculated. Now, a (hidden) table is held on each character sheet which holds saving throw and attribute check modifiers currently in force, with a name and a source, and optional durations in number of saves to which the mod applies and/or the number of rounds duration of the mod. The mods can apply to one type of save/check, more than one, or all. The mods are specific to the character represented by the sheet. Commands exist (documented in the AttackMaster Help Handout) to add, modify, and delete the mods.
'
+ +'
This new system can also be used to create totally new, bespoke saving throws based on any existing saving throw, which can be modified. For existance, the spell Bless only affects saves against Fear effects. Using the new mod commands a new "save vs. Fear" button can be added to the Saving Throw table for the duration of the Bless only for those characters who are blessed, which is based on a save vs. spell but with a +1 bonus.
'
+ +'
At any time, the player can review the way their character\'s saving throws and ability checks are calculated by selecting the [Auto-check Saving Throws] button on the Saving Throw dialog, or equivalent button on the Attribute Check dialog.
'
+ +'
Status Targeting with Saving Throws
'
+ +'
The RoundMaster --target command (and associated other token status management commands) can now take a saving throw specification as the last argument, defining the type of save required and any bonus or penalty to the save. This only works if RoundMaster is being used with AttackMaster. The effect of adding this optional parameter is that the player issuing the command will be prompted to ask the player controlling the target token to make the appropriate saving throw and, if that saving throw is made using the AttackMaster saving throw dialog (which will apply the bonus or penalty as specified in the new parameter), a failure will automatically apply the status and any associated effects to the token. If the save is made the status is not applied.
'
+ +'
Multi Mode for Status Targeting
'
+ +'
Multi has been added as a command mode for the RoundMaster --target command, alongside the existing caster, single, and area modes. Multi mode is similar to area, but allows the player to shift-select multiple tokens at the same time, and then click one button to apply the status to all those tokens. If the new saving throw parameter (see above) is included, the player will be prompted to ask for saving throws to be made for all the selected tokens - which can all happen simultaneously with the outcomes described above.
'
+ +'
For the multi command, RPGM maths for the duration, direction and/or saving throw mods can include the symbol \'#\' which will be replaced with the number of tokens selected and allow these numbers to vary by the number of tokens targeted. This is useful where saving throw bonuses or penalties vary by numbers of targets, or the duration is divided across the targets, for instance.
'
+ +'
Important Note: When this new multi mode is used for a --target command, at the point the command is entered all tokens on the same Roll20 page as the caster token temporarily become controllable (and thus selectable) by the player controlling the caster token. Also, all tokens without controllers (or otherwise controlled by the GM) that have sight under Dynamic Lighting will be temporarily "blinded" - this is so that the player controlling the casting token is not suddenly able to see the whole map, and the dynamic lighting Explorer Mode is not compromised. The temporary blinding and control are automatically removed as soon as the casting player clicks the button to apply the statuses or issues any other API command (RPGM or otherwise).
'
+ +'
Simplified Status Targeting Confirmation
'
+ +'
Options have been provided for better control over the requirement for the GM to confirm all targeted token status changes made by a player using RoundMaster --target command. Two new qualifying command modifiers now exist: --target-nosave and --target-save. The first will not prompt the GM for a confirmation when applying a status to a token (though this behaviour can be altered using the --nosave command), whereas the second will always prompt for confirmation even if the command is issued by the GM. --target-nosave is useful when casting a spell or an item power that has no saving throw e.g. where applied to the caster themselves. --target-save can be useful to remind the GM to prompt for or make saving throws. The --nosave command will turn off or on the --target-nosave behaviour.
'
+ +'
Action Buttons Disabled on View
'
+ +'
When spell and item descriptions are viewed (rather than cast or used) all action buttons in the spell or item macro are now "greyed out" and not selectable, so that effects are not inadvertently applied and charges aren\'t accidentally used due to the player selecting an action button. The one exception is for any action buttons that start with "View" in the button text - this allows, for instance, players to still view the spells contained in a spell-storing magic item.
'
+ +'
Renaming of Non-Stackable Loot
'
+ +'
Some items are not stackable in containers or character\'s backpacks, such as wands with charges or spell-storing items. However, it is also the case that items in containers should have unique names to identify them, so if two of the same non-stackable items are found, one of them needs to be renamed. This is now automatically detected and the player prompted to enter a new name for the second (or subsequent) items picked up. The renamed item retains all its properties, powers, stored-spells, etc.
'
+ +'
Configurable Automatic Hits & Misses
'
+ +'
To date, automatic hits on a natural 20, or automatic miss on a natural 1, have had to be applied manually on targeted attacks. By default, automatic hits and misses will now be applied for targeted attacks but with an RPGM Configuration option to turn this off. Similarly, Critical Hits and Misses (which need not be equivalent to natural rolls of 20 & 1) now also automatically hit or miss on targeted attacks and also have a separate RPGM configuration option to turn this off.
'
+ +'
Updated Database Items to Latest Features
'
+ +'
Now all magic items defined in the AD&D2e Dungeon Master\'s Guide have been defined in the RPGM databases, the on-going task of updating and refining them has started. Potions, scrolls, and rings have been reviewed and updated - though the impact will seem very limited to those using them. All spells, both Clerical and Wizard, and all Powers, have also been updated.
'
+ +'
Spell Databases Split by Level
'
+ +'
In order to make spell databases more manageable, they have been split by level, with Wizard spell databases now being MU-Spells-DB-L# and Clerical spell databases being PR-Spells-DB-L#. This will not affect any currently extracted spell databases or DM\'s custom spell databases, which will continue to function as before. The only visible impact is on extracting databases where a choice of databases will now be offered when extracting spell databases.
'
+ +'
Added Ceiling & Floor to RPGM Maths
'
+ +'
The RPGM alternative to Roll20 maths for numeric values now includes ceiling and floor operators. c(...) will return the value in the brackets rounded up and f(...) will return it rounded down.
'
+ +'
Fixes
'
+ +'
While I am sure everything worked when first coded, subsequent changes have had unexpected consequences and players have also done things I didn\'t expect (is that not the story for all GMs?). Hence fix lists continue...
'
+ +'
'
+ +'- Fixed magic item rev: (reveal hidden item trigger) database attribute
'
+ +'- Fixed --display-attribute to properly support %{...|...} and database item variables
'
+ +'- Fixed ^^duration^^ tag in effect macros to insert the current remaining duration of the status
'
+ +'- Fixed use of \'=#\' when setting override initiative modifiers and for --mi-charges
'
+ +'- Fixed default ToHit dice specification in getToHitRoll() if ToHit dice are not specified in the Attack macro
'
+ +'- Replaced MIrowref lookup when making magic attacks as might not be pointing to correct magic item
'
+ +'- Fixed errors in renaming magic items when new name includes all or part of the old name
'
+ +'- Fixed spell-storing items with the -ADD command qualifier to correctly allow the character/player to add new spells
'
+ +'- Fixed stacking of identical items looted and already in pack
'
+ +'- Fixed drag & drop container with no traps
'
+ +'
'
+ +'
',
+ },
+ RPGM_Templates_Handout: {name:'RPGMaster Library Help',
+ version:1.06,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGMaster Library Help v1.06'
+ +'
'
+ +''
+ +'
RPGMaster Library and Templates
'
+ +'
for all RPGMaster APIs
'
+ +'
New in this Help Handout
'
+ +'
- New Template tag hide# to trigger [show more..] button
'
+ +'
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 Dice Rolls and Roll Reuse
'
+ +'
As with any message sent to the Roll20 chat window, it is possible to use standard functions such as in-line rolls and maths. These all work in exactly the standard way that they do in any other template or message. In some fields of an RPGMaster template, such as those being used to assess success criteria for a {{Result= ... }}, such rolls and calculations are necessary and important.
'
+ +'
Just as useful is the ability to reuse the value of in-line rolls at other points in the RPGMaster roll templates. In order to reuse a roll result, use the syntax $[[#]], where # is the 1-based index of which roll in the template is being reused. For example, here is a template used for a power that only deducts a charge of the magic item that cast the power if the dice roll of 1d10 is equal to the value 2, but a roll of 1 is also a success, and anything other than 1 or 2 is a failure:
'
+ +'
Improve Gem
'
+ +'
&{template:RPGMdefault}{{title=@{selected|token_name} attempts to
**Improve a Gem**
using a *Jewel of Flawlessness*}}Specs=[Improve Gem,Power,1H,Alteration]{{Speed=[[10]]}}{{Range=0}}{{Duration=Permanent}}{{Area of Effect=Jewels in same container with *Jewel of Flawlessness*}}{{save=None}}{{reference=DMG p173}}SpellData=[w:Improve Gem,sp:10,cs:M]{{desc=When a jewel of flawlessness is placed with other gems, it doubles the likelihood of their being more valuable (i.e., the chance for each stone going up in value increases from 10% to 20%). The jewel has from 10-100 facets, and whenever a gem increases in value because of the magic of the jewel of flawlessness (a roll of 2 on d10), one of these facets disappears. When all are gone, the jewel is a spherical stone that has no value.}}{{Need to Roll=2 or less}}{{Improvement Roll=[[1d10]]}}{{Result=Need to Roll>=Improvement Roll}}{{successcmd=!magic ~~mi-charges @{selected|token_id}¦-[[$[[1]]-1]]¦Jewel-of-Flawlessness¦¦charged}}
'
+ +'
The {{Need to Roll=2 or less}} sets the target that represents success. The in-line roll is included in {{Improvement Roll=[[1d10]]}}. The two values are compared in the {{Result=Need to Roll>=Improvement Roll}} which results in Success or Failure being displayed on the Roll Template in the chat window and, if successful, the {{successcmd=...}} command being run. In this case, the command is a call to the !magic --mi-charges function that will deduct charges from the magic item named in the call in the character\'s equipment bag. But a charge is only deducted if the roll of the dice is 2, as per the specification of the magic item in the DMG. To use the value of the in-line roll in both calculating the Result and use in the successcmd command, the roll needs to be referenced in the successcmd using the $[[1]] reference syntax as part of the in-line calculation [[$[[1]]-1]]. As successcmd will only execute on success of the Result, which happens if the in-line dice roll is 1 or 2, "successful dice roll minus 1" is 0 or 1, and negating this is -0 on a roll of 1 and -1 on a roll of 2.
'
+ +'
If there were more rolls, these would be referenced using $[[2]], $[[3]], ... etc.
'
+ +'
2.4 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, an example being 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 | RPGMAttack: 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. RPGMdefault: Same as Result, but displays a green Critical Success! bar if true. |
'
+ +' Fumble Roll | Optional | RPGMattack: 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. RPGMdefault: Same as Result, but displays a red Critical Failure! bar if true. |
'
+ +' CritCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Crit_Roll comparison is true. Normally used to execute an API command on a critical success |
'
+ +' FumbleCmd | Optional | The text provided will not be displayed but will be sent to the chat window if the Fumble Roll comparison is true. Normally used to execute an API command on a fumble |
'
+ +' 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. |
'
+ +' Looks Like | Optional | A description of what the item looks like (for potions & scrolls), especially useful for hidden items. |
'
+ +' 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. If desc(1-9) are used, a button to show less... will appear in the {{desc=...}} section which, if selected, will change the desc(1-9) to hide(1-9) and not display it. |
'
+ +' New Hide(1-9) | Optional | Up to 9 rows of text tagged with hide(1-9) will not be shown, but will trigger a show more... button to be added to the desc section which, if selected, will redisplay the template with "hide(1-9)" changed to "desc(1-9)" and displayed. |
'
+ +'
'
+ +'
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. |
'
+ +' Looks Like | Optional | A description of what the item looks like, especially useful for hidden items. |
'
+ +' 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. If desc(1-9) are used, a button to show less... will appear in the {{desc=...}} section which, if selected, will change the desc(1-9) to hide(1-9) and not display it. |
'
+ +' New Hide(1-9) | Optional | Up to 9 rows of text tagged with hide(1-9) will not be shown, but will trigger a show more... button to be added to the desc section which, if selected, will redisplay the template with "hide(1-9)" changed to "desc(1-9)" and 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 write the values to. If the row number is beyond the current end of the table, will create all the fields in a new row of 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 fields 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.
'
+ +'
'
+ +'
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:2.01,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'RPGMaster CharSheet Setup v2.01'
+ +'
'
+ +''
+ +'
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 default bar assignments set by the CommandMaster API if its facilities are used to set up the tokens: the CommandMaster functions can be used to change the defaults to whatever you require. However the bars are set (using CommandMaster or manually), the APIs will always 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 the default fields on the token. It is recommended that all tokens are set the same way, whatever way you eventually choose.
'
+ +'
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\', as well as many of their sub-races, 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, as well as granting some racial powers.
'
+ +'
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 entered manually, if a weapon or its related weapon group does not appear in the list, it will be assumed to be not proficient. However, if CommandMaster is used to set proficiencies, just having proficiency in a weapon will mean automatic related weapon proficiency in any related weapon.
'
+ +'
9. 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.
'
+ +'
10. 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.24,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Weapon & Armour Database Help v1.24'
+ +'
'
+ +''
+ +'
Weapon and Armour Databases
'
+ +'
for AttackMaster v'+version+' and later
'
+ +'
New in this Help Handout
'
+ +'
'
+ +'- New Item Inheritance
'
+ +'- New Dancing Weapons
'
+ +'- New Configurable Items and the Query Attribute
'
+ +'
'
+ +'
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.
'
+ +'
1.2 New Item Inheritance
'
+ +'
Item definitions can be simplified using item inheritance, where an item definition can inherit data attributes and Roll Template text from a "parent item". This is fully explained in the Magic Database Help handout and not repeated here, so please refer to that help handout for further information on this very helpful feature.
'
+ +'
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.
'
+ +'
Important Note: Magical self-Ammoed / Thrown weapons must only have the magical bonus (or penalty for cursed items) defined in the AmmoData +: attribute. This will be added both to the To-Hit calculation and to the Damage calculation. The ToHitData +: attribute should be set to +:0 or not specified at all (defaults to 0) as otherwise the To-Hit calculation will gain both a plus from the ToHit data and also from the AmmoData. This is equivalent to having a separate ranged weapon (such as a bow) with +:0 (the normal state) firing magical ammunition (such as Flight Arrow+1).
'
+ +'
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.
'
+ +'
New Dancing Weapons
'
+ +'
Only one dancing weapon is defined in the Dungeon Master\'s Guide, the "Sword of Dancing". However, with RPGMaster APIs, any weapon can be made to dance including ranged weapons:
'
+ +'
Longsword of Dancing
'
+ +'
&{template:RPGMweapon}{{title=Longsword of Dancing}} {{subtitle=Magical Sword}}{{Speed=[[5]]}} {{Size=Medium}}WeapData=[d:+1/4]{{Weapon=Dancing 1-handed melee long-blade}}Specs=[Longsword,Melee,1H,Long-blade]{{To-hit=+1/2/3/4 on sequential rounds + Str bonus}}ToHitData=[w:Longsword of Dancing, 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=+1/2/3/4 on sequential rounds, vs SM:1d8, L:1d12, + Str bonus}}DmgData=[w:Longsword, sb:1, +:0, SM:1d8, L:1d12]{{desc=This is a very special sword. It is etched with dramatic battle scenes, almost balletic in grace and poise.}}
'
+ +'
This weapon will automatically be identified as a "dancing weapon" when taken In-hand using the Attk Menu > Change Weapon dialog. The necessary data attribute to be placed in the WeapData section is shown below:
'
+ +'
'
+ +'d: | [+/-]# [|#] | Defines the change in magical plus per round, optionally followed by a pipe and number of dancing rounds (defaults to 4) |
'
+ +'
'
+ +'
Such a weapon must be held in-hand (and presumably used to attack) for a number of rounds before it will dance, with the magical plus of the weapon changing by a defined amount each round (which can be positive, zero or negative). Once that number of rounds has passed, the weapon will automatically start dancing, and the player will be presented with the Change Weapon dialog to select a new weapon to take in hand. The dancing weapon will automatically be given an initiative roll each round while dancing, the magical plus will be reset to that defined for the first round in the specification and will again increment round on round. Once the number of rounds has again passed, the weapon will stop dancing: the player will need to take the weapon in-hand again to restart the sequence.
'
+ +'
Note: the magical plus of the weapon on the first round in the sequence will always be that specified by the +:# attribute incremented by the dancing increment from the d:[+/-]# attribute. Thus a ToHitData and DmgData entru of +:0 and a WeapData specification of d:+1/4 will result in the first round plus being +1.
'
+ +'
Dancing weapons work by using Effects managed by the RoundMaster API, which needs to be loaded for them to work. This weapon definition will automatically create the required effects for RoundMaster to use (using the !rounds --dancer command), which will work in a standard way, following the approach for a "Sword of Dancing" defined in the DMG. If you want a specialised dancing weapon using a different approach, you will need to define your own dancing weapon effects using the information in the Effects Database Help handout.
'
+ +'
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 |
'
+ +'
Execute a command on attack or doing damage
'
+ +'
As with executing a command when drawing or sheathing a weapon, simple commands which do not include multiple lines or Roll20 macro calls can be included in the ToHitData specification for attack commands, in the DmgData specification for melee weapon damage commands, and in the AmmoData specification for ranged weapon damage commands.
'
+ +'
cmd: | <command> | A simple command that can be expressed on a single line, execution occuring at a point determined by which data set the tag is in |
'
+ +'
A typical use of such a command is in the ToHitData or DmgData of a weaponised spell:
'
+ +'
&{template:RPGMspell}{{title=@{selected|Casting-name} casts Wither as a level @{selected|Casting-Level} caster}}{{splevel=Level 7 Priest}}{{school=Necromancy (Reversable)}}{{sphere=Necromantic}}Specs=[Wither,Innate-Melee|PRspellL7,1H,Necromancy]{{components=V,S,M}}{{range=Touch attack}}{{time=[[1]] round}}{{duration=Permanent}}{{aoe=Creature Touched}}ToHitData=[w:Wither,sp:1,sb:0,ty:SPB,r:5,msg:A successful hit withers the member or organ touched ceasing to function in 1 round and dropping off into dust in \\lbrak;2d4 turns\\rbrak;\\lpar;!rounds ~~target single¦`{selected¦token_id}¦@{target¦Who\'s member will wither?¦token_id}¦Wither¦[\\lbrak;10*2d4\\rbrak;]¦-1¦Touched limb / member / organ is withering and turning to dust¦back-pain\\rpar;,cmd:!attk ~~blank-weapon `{selected¦token_id}¦Wither¦silent]{{save=None}}DmgData=[w:Wither,sb:0,SM:0,L:0,msg:A successful hit withers the member or organ touched ceasing to function in 1 round and dropping off into dust in \\lbrak;2d4 turns\\rbrak;\\lpar;!rounds ~~target single¦`{selected¦token_id}¦@{target¦Who\'s member will wither?¦token_id}¦Wither¦[\\lbrak;10*2d4\\rbrak;]¦-1¦Touched limb / member / organ is withering and turning to dust¦back-pain\\rpar;]{{reference=PHB p234}}SpellData=[w:Wither,lv:7,sp:1,gp:0.1,cs:VSM,sph:Necromantic]{{Use=Take the spell in-hand when casting, and attack with it. Called shots attract penalties to hit.}}{{effects=Causes the member or organ touched to cease functioning in one round, dropping off into dust in 2d4 turns. Creatures must be touched for the harmful effect to occur.}}{{materials=A prayer device and unholy water}}
'
+ +'
In this case, the command !attk --blank-weapon @{selected|token_id}|Wither|silent is included in the ToHitData specification and removes the spell as a weapon as soon as the caster attacks, whether successful or not. If this command had, instead, been included in the DmgData specification, the spell would have remained a usable weapon until the touch was successful and the damage done.
'
+ +'
New Configurable Items and the Query Attribute
'
+ +'
It is possible to create weapon (and armour) definitions at have configurable elements, set when the item is first added to a container or a character. This is achieved using the query: attribute in the "WeapData" or "ACdata" section of the item. An example of its use is the Magical Javelin which uses a query to ask what magical plus that armour might grant, including negative / cursed values.
'
+ +'
Magical Javelin
'
+ +'
&{template:RPGMweapon}{{prefix=^^weaponMagic#2^^}}{{title=Javelin}}{{name=^^weaponMagic#0^^}}Specs=[Javelin,Melee,1H,Spears], [Javelin,Melee,2H,Spears], [Javelin,Ranged,1H,Throwing-Spears]{{}}WeapData=[w:Javelin, query:weaponMagic=How magical is this weapon?|+0%%0/ |-4%%-4/Cursed |-3%%-3/Cursed |-2%%-2/Cursed |-1%%-1/Cursed |0%%0/ |+1%%1/ |+2%%2/ |+3%%3/ |+4%%4/, st:Javelin, +:^^weaponMagic#1^^, rc:^^weaponMagic#2^^]{{}}ToHitData=[w:Javelin^^weaponMagic#0^^, +:^^weaponMagic#1^^, sb:1, n:1, ch:20, cm:1, sz:M, ty:P, r:5, sp:4],[w:Javelin 2H^^weaponMagic#0^^, +:^^weaponMagic#1^^, sb:1, n:1, ch:20, cm:1, sz:M, ty:P, r:5, sp:4],[w:Javelin^^weaponMagic#0^^, +:0, sb:1, db:1, n:1, ch:20, cm:1, sz:M, ty:P, sp:4]{{}}DmgData=[w:Javelin^^weaponMagic#0^^, +:^^weaponMagic#1^^, sb:1, SM:1d4, L:1d4],[w:Javelin 2H^^weaponMagic#0^^, +:^^weaponMagic#1^^, sb:1, SM:1d6, L:1d6, msg:Does double damage if set against charge],[]{{}}AmmoData=[w:Javelin^^weaponMagic#0^^, +:^^weaponMagic#1^^, t:Javelin, st:Spear, sb:1, SM:1d4, L:1d4]{{}}RangeData=[t:Javelin, +:^^weaponMagic#1^^, r:2/2/4/6]{{}}%{MI-DB|Weapon-Info}{{}} %{MI-DB|Magical-Weapon-Info}{{subtitle=^^weaponMagic#2^^ Spear}} {{subtitle=Spear}} {{Speed=[[4]]}} {{Size=Medium}} {{Weapon=1-or 2-handed ^^weaponMagic#2^^ melee or thrown spear}} {{To-hit=^^weaponMagic#0^^ + Str Bonus}}{{Attacks=1 per round + level & specialisation, Piercing}}{{Damage=^^weaponMagic#0^^, 1H vs SM:1d4, L:1d4, 2H vs SM:1d6, L:1d6 + Str bonus}} {{Ammo=^^weaponMagic#0^^, vs SM:1d4, L:1d4 + Str bonus}} {{Range=PB:20 S:20 M:40 L:60}} {{Looks Like=Javelins are classified as light spears, suitable for melee or missile combat, usable either on horseback or on foot. Javelins may be used either one- or two-handed, and like the harpoon, there is no difference in speed factor between the two styles.}} {{desc=This is an exceptional Javelin. It is light and has a sharp point, and might be special in some way or other.}}
'
+ +'
The query: attribute in the WeapData section defines the questions that will be asked in standard Roll20 Roll Queries. In this case, a question about the magical bonus (or penalty) is asked using the following format:
'
+ +'
result-tag=query question|option 1 text%%value 1.1/value 1.2/.../value 1.n|option 2 text%%value 2.1/value 2.2/.../value 2.n|...%%.../.../...|option j text%%value j.1/value j.2/.../value j.n
'
+ +'
Multiple queries can be concatinated, separated by \'$$\'. Each query posts the option texts in a list. The selected option will then provide the values that substitute dynamic attributes in the data section, which are specified with the syntax ^^result-tag#n^^
where \'n\' is the value index - index 0 is the option text itself. Using the Magical Javelin example, selecting a cursed weapon penalty of -2 replace the following dynamic attributes:
'
+ +'
'
+ +'w:Javelin^^weaponMagic#0^^ | w:Javelin-2 |
'
+ +'+:^^weaponMagic#1^^ | +:-2 |
'
+ +'rc:^^weaponMagic#2^^ | rc:Cursed |
'
+ +'
'
+ +'
In fact, there are three pre-defined weapon queries that can be used after the query: attribute that will save some typing:
'
+ +'
'
+ +'Attribute | Resolves to |
'
+ +'query:weaponPlus | query:weaponPlus=How magical is this weapon?|+0%%0/|+1%%1/|+2%%2/|+3%%3/|+4%%4/ |
'
+ +'query:weaponMagic | query:weaponMagic=How magical is this weapon?|+0%%0/|-4%%-4/Cursed|-3%%-3/Cursed|-2%%-2/Cursed|-1%%-1/Cursed|0%%0/|+1%%1/|+2%%2/|+3%%3/|+4%%4/ |
'
+ +'query:weaponCurse | query:weaponCurse=How cursed is this weapon?|-0%%0/Cursed/|-1%%-1/Cursed|-2%%-2/Cursed|-3%%-3/Cursed|-4%%-4/Cursed |
'
+ +'query:swordType | swordType=What type of sword?|Longsword%%M/S/5/1d8/1d12/M/S/5/1d8/1d12|Broadsword%%M/S/5/2d4/1+1d6/M/S/5/2d4/1+1d6|Bastard-Sword%%M/S/6/1d8/1d12/M/S/8/2d4/2d8|Khopesh%%M/S/9/2d4/1d6/M/S/9/2d4/1d6|Shortsword%%S/P/3/1d6/1d8/S/P/3/1d6/1d8|Scimitar%%M/S/5/1d8/1d8/M/S/5/1d8/1d8|Two-Handed-Sword%%L/S/10/0/0/L/S/10/1d10/3d6] |
'
+ +'
'
+ +'
Thus the query: attribute in the example could have been shortened to "query:weaponMagic,".
'
+ +'
The Specs specification cannot use query variables. Thus, as the weapon type can vary if using the swordType pre-defined query shortcut (or a similar construct) there is an alternative approach to specifying the weapon type (and supertype if needed) by using the \'t:\' and \'st\' attributes in the ToHitData section. Each of these can be followed by a literal string defining the type or, more usefully, a query variable (e.g. t:^^swordType#0^^):
'
+ +'
'
+ +'t: | Define the type of weapon for determination of proficiency |
'
+ +'st: | Define the tight weapon-group of weapon for determination of related weapon proficiency |
'
+ +'
'
+ +'
These attributes override the values given for the 1st and 4th fields in the Specs section.
'
+ +'
'
+ +'
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 | | X |
'
+ +' st: | < text > | \'\' | Group Type (aka Tight-Group) | X | | 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 | | | | | |
'
+ +' d: | [ + / - ] # [ | # ] | \'\' | Dancing increment / duration | | | | | 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 | X | X | 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.
'
+ +'
',
+ },
+ SpellsDatabase_Help:{name:'Spells Database Help',
+ version:1.32,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Spells Database Help v1.32'
+ +'
'
+ +''
+ +'
Spell & Power Database Help
'
+ +'
for MagicMaster v'+version+' and later
'
+ +'
New in this Help Handout
'
+ +'
'
+ +'- New Split out Spell & Power Help to separate handout
'
+ +'
'
+ +'
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 MagicMaster API command !magic --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. 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).
'
+ +'
Other spells may not persist beyond the first attack with the spell, or perhaps after the first successful attack: this is often the case with spells that require the caster to "touch" an unwilling target.
'
+ +'
&{template:RPGMspell}{{title=@{selected|Casting-name} casts
Cause Blindness or Deafness
as a level @{selected|Casting-Level} caster}}{{splevel=Level 3 Priest (reversable)}}{{school=Abjuration}}{{sphere=Necromantic}}Specs=[Cause-Blindness-or-Deafness,Innate-Melee|PRspellL3,1H,Abjuration],[Cause-Blindness-or-Deafness,Innate-Melee|PRspellL3,1H,Abjuration]{{components=V,S}}ToHitData=[w:Cause Blindness,sp:10,r:5,touch:1],[w:Cause Deafness,sp:10,r:5,touch:1]{{time=[[10]]}}DmgData=[w:Cause Blindness,sm:0,l:0,cmd:!rounds ~~target single¦`{selected¦token_id}¦`{target¦Which creature is the victim?¦token_id}¦Blindness¦99¦0¦Blinded and suffer -4 penalty to attacks and AC and +2 penalty to initiative¦bleeding-eye],[w:Cause Deafness,sm:0,l:0,cmd:!rounds ~~target single¦`{selected¦token_id}¦`{target¦Which creature is the victim?¦token_id}¦Deafness¦99¦0¦Deafened and suffer +1 penalty to initiative as well as other effects¦bleeding-eye]{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=Negates}}{{reference=PHB p209 (reverse Cure Blindness or Deafness)}}SpellData=[w:Cause-Blindness-or-Deafness,lv:3,sp:10,gp:0,cs:VS,sph:Necromantic]{{use=Take the spell in-hand using the *change weapon* dialog, then use the *attack* action to select which effect and attack a target}}{{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.
A *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. 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.}}
'
+ +'
The ToHitData, DmgData, or AmmoData specifications can include the data tag touch:
'
+ +'
'
+ +' touch: | [ 0 / 1 ] | The spell expires if touch:1 is used (defaults to 0 if not specified) |
'
+ +'
'
+ +'
If the touch:1 data tag and value is included in the ToHitData (whether a melee touch spell or a ranged attack spell) the spell will expire and be removed as an available attack on the first attack with the spell. If the touch:1 is included in the DmgData (for melee touch spells) or AmmoData (for ranged attack spells) the spell will remain available as an attack until a successful attack is made and damage or an effect occurs: this works whether or not using targeted attacks or otherwise, with non-targeted attacks expiring if either the S/m or L damage buttons are selected on the AC Hit dialog.
'
+ +'
Executing commands when attacking or doing damage
'
+ +'
Sometimes a spell will need some command to be executed when an attack is made, either only when the attack is successful or when any attack is attempted. The above example of the Cause Blindness or Deafness spell is also an example of a spell using a command on a successful attack. It uses the cmd: data tag:
'
+ +'
'
+ +' cmd: | cmd-string | A command to be executed when the magical attack is made, encoded with the standard and extended RPGMaster escape sequences |
'
+ +'
'
+ +'
If the cmd:cmd-string data tag and value is included in the ToHitData specification then the command specified will execute automatically whenever the spell is used to do an attack, whether successful or not. If the cmd:cmd-string is included in the DmgData or AmmoData specifications the command will execute only when an attack is successful.
'
+ +'
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.
'
+ +'
'
+ +'
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.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 | '
+ +' AC Data | '
+ +'
'
+ +' '
+ +' w: | < text > | \'-\' | Name to be displayed | | X | 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 | X |
'
+ +' n: | # [ / # ] | 1 | Attacks per round | | | | X | X | X | | X | X | |
'
+ +' st: | \' \' | \'\' | Item type to display | | X | X | X | X | X | X | X | | X |
'
+ +' sz: | [ t / s / m / l / h ] | \'\' | Size of item | | | | X | 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 | X |
'
+ +' rules: | [+/-][rule] | ... | 0 | Save / Check rules | | | | X | X | X | X | X | | X |
'
+ +' svXXX: | [=][+/-]# | 0 | Save / Check mod | | | | X | X | X | X | X | | X |
'
+ +' on: | command | \'\' | Cmd to execute when worn | | | | X | X | X | X | | | |
'
+ +' off: | command | \'\' | Cmd to execute when removed | | | | X | X | X | X | | | |
'
+ +' ns: | # | 0 | Number of stored spells & powers defined for item | | | X | 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 | | 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 | | 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 | 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 | 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 | |
'
+ +' learn: | [ 0 | 1 ] | 0 | Learnable stored spells | | | 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.
'
+ +'
',
+ },
+ MIDatabase_Help: {name:'Magic Database Help',
+ version:1.34,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Magic Database Help v1.34'
+ +'
'
+ +''
+ +'
Magic Item Database Help
'
+ +'
for MagicMaster v'+version+' and later
'
+ +'
New in this Help Handout
'
+ +'
'
+ +'- New Items that affect initiative rolls
'
+ +'- New Items that execute commands on being picked up and/or put away
'
+ +'
'
+ +'
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 MagicMaster API command !magic --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.
'
+ +'
'
+ +'
Note: Help for Spells & Powers has been split out to its own help handout.
'
+ +'
2. 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.
'
+ +'
2.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.
'
+ +'
2.2 Item Inheritance
'
+ +'
All magic item definitions (including those for weapons, ammunition & armour) can inherit data, specifications and text from other similar magic item definitions. For example, the "Ring of Protection+2" is very similar to the "Ring of Protection+1" described in 2.2 above, and can inherit most of its specification from there:
'
+ +'
&{template:RPGMring}{{}}Specs=[Ring of Protection,Protection Ring,1H,Abjuration-Protection,Ring-of-Protection+1]{{}}ACData=[a:Ring of Protection+2,+:2,svsav:2,w:Ring of Protection+2]{{}}%{MI-DB|Ring-of-Protection+1}{{name=+2}}{{Protection=+[[2]] on AC}}{{Saves=+[[2]] on saves}}
'
+ +'
Inheritance comes in two forms: data inheritance and text inheritance.
'
+ +'
Data Inheritance: an optional 5th parameter can be added to the Specs section, and RPGMaster will look for a magic item of that name: if not provided the 4th parameter will be used in the same way. If an item of that name is found (e.g. in this case "Ring-of-Protection+1") the data in data sections of the same name (e.g. "ACdata=") will be merged - data provided in the inheriting item (in this case "Ring-of-Protection+2") will take priority over inherited data (e.g. svsav:2 will override the inherited svsav:1). This inheritance can be nested as desired - the item being inherited from (the "parent item") can iteself inherit from another (the "grand-parent item").
'
+ +'
Text Inheritance: If you are familiar with Roll20 ability macro programing, you will recognise the syntax %{char-name|ability-name} to insert the text of an ability macro into the chat window or another ability macro. RPGMaster item definitions do something similar but important to note not exactly the same! Instead of using the "char-name" a database name or database root name is given (e.g. "MI-DB-Weapons" or just "MI-DB") followed by the pipe \'|\' and the inherited item name. This will search both character sheet databases and databases held in memory - even if a specific database name is given, if not found in a database of that name all databases of the same root will be searched (e.g. if MI-DB-Rings is specified and the item not found there, all MI-DB databases will be searched). Note: under Text Inheritance data sections will not be merged (unless Data Inheritance is also used). Roll Template sections with the same name later in the merged definition take precidence (e.g. in this example the Roll Template section {{Protection=+[[2]] on AC}} will override that from the Ring-of-Protection+1 because it comes after the %{...|...} in the Ring-of-Protection+2 "child" item definition).
'
+ +'
Defining Parent / Child item inheritance in this way can make the databases much smaller, allow simpler maintenance of common inherited data attributes, and cause less typing!
'
+ +'
2.3 Items that Protect
'
+ +'
Items like a Ring of Protection or a Luck Blade protect the possessor by improving their saving throws and/or armour class.
'
+ +'
Ring of Protection+2
'
+ +'
&{template:RPGMring}&{template:RPGMring}{{name=Ring of Protection}}{{subtitle=Ring}}{{Speed=[[0]]}}{{Size=Tiny}}{{Immunity=None}}{{Protection=+[[2]] on AC}}Specs=[Ring of Protection,Protection Ring,1H,Abjuration-Protection]{{Saves=+[[2]] on saves}}ACData=[a:Ring of Protection+2,st:Ring,+:2,rules:-magic,sz:T,wt:0,svsav:2,w:Ring of Protection+2,sp:0,rc:uncharged,loc:left finger|right finger]{{Looks Like=A relatively plain ring made of some exotic metal. You are unable to distinguish it from any other ring by just looking at it...}}{{desc=A ring of protection improves the wearer\'s Armour Class value and saving throws versus all forms of attack. A ring +1 betters AC by 1 (say, from 10 to 9) and gives a bonus of +1 on saving throw die rolls. The magical properties of a ring of protection are cumulative with all other magical items of protection except as follows:
1. The ring does not improve Armour Class if magical armour is worn, although it does add to saving throw die rolls.
2. Multiple rings of protection operating on the same person, or in the same area, do not combine protection. Only one such ring—the strongest—functions, so a pair of protection rings +2 provides only +2 protection.}}
'
+ +'
All items that protect that are not armour or shields have an item class of some type of protection-[item] specified as the second field of the Specs for the item. The [item] text can be anything you desire, e.g. in this case protection-ring, but only the most advantageous protection-[item] that the possessor has on them will operate. E.g. a protection-ring will work with a protection-cloak but not with another protection-ring.
'
+ +'
Items that protect that have an effect on armour class must use the ACData section to specify their properties, otherwise the properties can be held in any other \'...data=\' specification. The Weapons & Armour Database Help handout has full specifications for ACData fields. The data field tags relevant to AC and saves are listed in the table below:
'
+ +'
'
+ +' +: | [+/-]# | The effect on armour class, + being beneficial, - being a penalty (ACData only). |
'
+ +' rules: | rule [ | rule | rule | ...] | Rules specifying what item types / supertypes / classes this item will or will not work with (see below). |
'
+ +' svXXX: | [=][+/-]# | The effect on various saving throws, specified by XXX, + being beneficial, - being a penalty. |
'
+ +'
'
+ +'
The rules: state conditions and which other items this item will or will not work with to improve armour class and/or saving throws. Each rule is separated by a \'|\' and preceeded by either \'+\' or \'-\'. The rules have the following meanings:
'
+ +'
'
+ +' +inHand | This item must be held in hand for them to work, using the Change Weapon dialog |
'
+ +' +worn | (Saves only) This item must be of a usable type that can be worn by the class / race of the character - default for AC |
'
+ +' -magic | (AC only) This item will not combine with magical armour |
'
+ +' -shield | (AC only) This item will not combine with a shield of any type |
'
+ +' -acall | (AC only) This item will not combine with any other armour (except that specified with a \'+\' - see below) |
'
+ +' -[supertype] | (AC only) This item will not work with any other item of the supertype specified |
'
+ +' +[supertype] | (AC only) This item will always work with any other item of the supertype specified, even if -acall rule has been specified |
'
+ +' -[item class] | (Saves only) This item will not combine with any other item of the item class specified |
'
+ +'
'
+ +'
The svXXX: entries state the effect on saving throws and/or ability checks that this item has if the rules are met. For Saving Throw mods the \'XXX\' can be one of \'par\', \'poi\', \'dea\', \'pet\', \'pol\', \'bre\', \'spe\', or \'sav\' each referring to the first 3 letters of the saving throw affected (or \'sav\' for all saving throw mods); and for Attribute Check mods \'XXX\' can be \'str\', \'con\', \'dex\', \'int\', \'wis\', \'chr\', and \'atr\' each refering to each Character attribute (or \'atr\' for all attribute mods); or to change all mods of both types use \'all\'. Each svXXX: field tag is followed by a number which can be optionally preceeded by \'+\' (a beneficial improvement to the mod), \'-\' (a penalty to the mod), and/or \'=\' (the mod is set to the value - overrides other changes).
'
+ +'
Note: Changing the Attribute mods will not affect the ability checks for open doors, bend bars, learn spells etc. These mods can only be adjusted manually using the appropriate button on the Attribute Check menu.
'
+ +'
2.4 New Items that change initiative
'
+ +'
In a similar way to protection, items can affect initiative roles for a character. This can only be achieved automatically if using group or individual initiative:
'
+ +'
Rod of Alertness
'
+ +'
&{template:RPGMring}&{template:RPGMwandspell}{{title=Rod}}{{name= of Alertness}}specs=[Rod of Alertness,melee,1h,Clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,magic,1h,clubs],[Rod of Alertness,Rod,1H,conjuration-summoning]{{splevel=Footman\'s mace/Rod}}weapdata=[w:Rod of Alertness,wt:10,st:Rod,init+:-1]{{school=Conjuration/Summoning}}tohitdata= ... ignore the rest for now...
All of the rod\'s protective functions require one charge. The animate object power require one additional charge, so, if all of the rod\'s protective devices are utilized at once, two charges are expended.
The rod can be recharged by a priest of 16th level or higher, as long as at least one charge remains in the rod when the recharging is attempted.}}{{use=Taking in hand as a weapon will improve initiative scores by 1 automatically. surprise bonus is manual, and allow use of the detection capabilities.
- selecting any of the detect buttons does not use a charge but will display the specifications of the spell and allow its effects to occur.
- when invoking alertness, the player should use the 120ft radius button to set the area of effect.
- selecting the light button should be used by the dm when alertness is triggered to point the cone of light in the right direction.
- the player should then select the 20ft radius button to show the aoe of the prayer
- then select the prayer spell button, which will expend a charge and allow the prayer effect markers to be set.
- selecting the [animate object] button will expend a charge and display the spell specs to allow it to have effect.}}
'
+ +'
The weapdata specification includes the attribute init+:-1 which indicates that this item improves the initiative priority roll by 1 (i.e. subtracting 1 from the roll). This will be automatically applied while the item obeys the rules specified for it - see the description of the rules: data attribute in 2.3 above. If the rules are met or no rules are specified for the item, the effect on initiative rolls will apply as long as the item is on the character\'s item list (not in their backpack).
'
+ +'
Another data attribute that modifies the initiative roll is the init*: attribute, which multiplies the attack actions each round for the possessing character (does not affect magic item use, spell casting or use of powers). a value above 1 increases attacks per round, and below 1 reduces those attacks.
'
+ +'
2.5 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 |
'
+ +'
'
+ +'
New Pick: and Put: field tags
'
+ +'
Other attributes that can work in a similar way execute commands when an item is "picked up" and added to a character or creature\'s items, and also when "put away" or passed on to another character, creature or container:
'
+ +'
'
+ +' pick: | Command string | A simple, single line command to execute on picking up the item |
'
+ +' put: | Command string | A simple, single line command to execute on putting away the item |
'
+ +'
'
+ +'
2.6 Weaponised Items using variable charges
'
+ +'
Some more complex items can be used as weapons that have different effects or damage depending on how many charges are expended:
'
+ +'
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. If combined with the special recharging type of \'enable\' then charges will not be deducted, but the c:value will still be compared against the quantity/number of charges of the item and the use disabled if there are fewer charges available than required. |
'
+ +' 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.
'
+ +'
2.7 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.
'
+ +'
2.8 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 text 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. However, if auto-hiding is set in the !magic --config options, an item with a Looks Like text tag will automatically be hidden in this way when added to any container. 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.
'
+ +'
It is possible to define the hidden status and the revealing trigger set when the item is added to a character or container as part of the data of the item definition. The hide: data tag can take the following parameters - if it is not specified, the auto-hide configuration flag defines the hiding status:
'
+ +'
'
+ +' hide | Automatically hide the item regardless of the state of the auto-hide configuration flag |
'
+ +' nohide | Do not hide the item regardless of the state of the auto-hide configuration flag |
'
+ +'
'
+ +'
The rev: data tag, which sets the trigger that will reveal a hidden item, can take the following values - if not defined, the reveal state is defined by the Reveal configuration flag:
'
+ +'
'
+ +' manual | Only reveal when the GM selects to do so using the [Add Item] dialog or the button shown on the item definition (to the GM only) |
'
+ +' view | Reveal the hidden item\'s true nature when the player first views the item\'s description once they have it in their possession |
'
+ +' nohide | Reveal the item\'s true nature when it is first used, but not if it is viewed before that |
'
+ +'
'
+ +'
2.9 Configurable Items and the Query Attribute
'
+ +'
It is possible to create item definitions at have configurable elements, set when the item is first added to a container or a character. This is achieved using the query: attribute in the data section of the item. An example of its use is the Armour of Blending which uses a query to ask which type of armour it really is and what magical plus that armour might grant.
'
+ +'
Armour of Blending
'
+ +'
&{template:RPGMarmour} {{title=Armour}} {{name=of Blending}}{{subtitle=Armour}} {{Armour=Can be any armour type}} Specs=[Armor-of-Blending,Armour,0H,MagicItem] {{AC=Varies by armour type}} ACData=[a:Armor of Blending, query:armourType=What type of armour? |Banded Mail%%Mail/4/2/0/1/Banded Armor (Disguise) |Brigandine%%Brigandine/6/1/1/0/Brigandine Armor |Bronze Plate Mail%%Mail/4/2/0/-2/Bronze Plate Mail (Disguise) |Chain Mail%%Mail/5/2/0/-2/Chain Mail |Field Plate%%Plate/2/3/1/0/Field Plate (Disguise)|Full Plate%%Plate/1/4/3/0/Full Plate (Disguise)|Leather%%Leather/8/0/-2/0/Leather Armor|Plate Mail%%Mail/3/3/0/0/Plate Mail (Disguise)|Ring Mail%%Mail/7/1/1/0/Ring Mail |Scale Mail%%Mail/6/0/1/0/Scale Mail |Splint Mail%%Mail/4/0/1/2/Splint Mail (Disguise) |Studded Leather%%Leather/7/2/1/0/Studded Leather $$ armourPlus=What magical plus? |0%%0 |+1%%1 |+2%%2 |+3%%3 |+4%%4 |+5%%5 , qty:1, st:^^armourType#1^^, t:^^armourType#0^^, +S:^^armourType#3^^, +P:^^armourType#4^^, +B:^^armourType#5^^, +:^^armourPlus#1^^, ac:^^armourType#2^^, sz:L, wt:40, loc:body, rac:^^armourType#6^^] {{Speed=[[0]]}} {{Size=Large}} {{Immunity=None}} {{Saves=No effect}} {{Looks Like=A normal suit of some type of armour (DM to determine).}} {{Use=When storing this armour, the DM/player will be asked to state what type of armour it is and its magical plus (if any). It will then operate as chosen and can be passed from container to container without further input.}} {{desc=This appears to be a normal suit of magical armor (determine type and AC modifier normally, ignoring negative results). However, upon command (a command word can be assigned if the DM desires), the armor changes shape and form, assuming the appearance of a normal set of clothing. The armor retains all its properties (including weight) when disguised. Only a *true seeing* spell will reveal the true nature of the armor when disguised.}}
'
+ +'
The query: attribute in the ACdata section defines the questions that will be asked in standard Roll20 Roll Queries. In this case, two separate questions are asked, each using the following format:
'
+ +'
result-tag=query question|option 1 text%%value 1.1/value 1.2/.../value 1.n|option 2 text%%value 2.1/value 2.2/.../value 2.n|...%%.../.../...|option j text%%value j.1/value j.2/.../value j.n
'
+ +'
Multiple queries can be concatinated, separated by \'$$\'. Each query posts the option texts in a list. The selected option will then provide the values that substitute dynamic attributes in the data section, which are specified with the syntax ^^result-tag#n^^
where \'n\' is the value index - index 0 is the option text itself. Using the Armour of Blending example, selecting an armour type of Plate Mail will replace the following dynamic attributes:
'
+ +'
'
+ +'t:^^armourType#0^^ | t:Plate Mail |
'
+ +'st:^^armourType#1^^ | st:Mail |
'
+ +'ac:^^armourType#2^^ | ac:3 |
'
+ +'+S:^^armourType#3^^ | +S:3 |
'
+ +'+P:^^armourType#4^^ | +P:0 |
'
+ +'+B:^^armourType#5^^ | +B:0 |
'
+ +'rac:^^armourType#6^^ | rac:Plate Mail (disguise) |
'
+ +'
'
+ +'
'
+ +'
3. 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.
'
+ +'
3.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.
'
+ +'
3.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.
'
+ +'
3.3 Flexible Spell-Storing Magic Items
'
+ +'
Some spell-storing magic items are more flexible in what they can do than the standard Ring of Spell Storing. Here is an example of one that the player character can add spells to, and alter the spells stored (within certain limits):
'
+ +'
Vibrant Purple Ioun Stone
'
+ +'
&{template:RPGMitem}{{name=(Vibrant Purple)}}Specs=[Ioun Stone,Miscellaneous,0H,Stone]{{}}MiscData=[w:Vibrant Purple Ioun Stone,st:Floating Vibrant Purple Stone,wt:2,sp:3,qty:2d6,lvl:1,store:any,rc:single-uncharged]{{}}%{MI-DB|Ioun-Stone}
{{Size=T}}{{Use=Can store "quantity" levels of spell that the possessor casts into it. [Store Spells](!magic --mem-spell MI-MU|@{selected|token_id}|Ioun-Stone-Vibrant-Purple) or [View Spells](!magic --view-spell MI|@{selected|token_id}|Ioun-Stone-Vibrant-Purple) or [Cast Spell](!magic --cast-spell MI|@{selected|token_id}||Vibrant Purple Ioun Stone||Ioun-Stone-Vibrant-Purple). The quantity/number of charges represents the number of levels of spell that can be stored.}}{{Looks Like=A vibrant purple prismatic stone that is floating in the air}}{{GM Info=This version of the Vibrant Purple Ioun Stone can store *any* spell and the player character can change the spells stored.}}
'
+ +'
This data definition has a couple of features not previously seen.
'
+ +'
The store: and lvl: data attributes: These attributes are unique to spell-storing magic items, and define limits on how spells can be stored in the item, using the !magic --mem-spell
command.
'
+ +'
'
+ +' lvl: | [ 1 / 0 ] | Defaults to \'0\'. Flag restricting the total levels of spell that can be cast into the item to be the item\'s qty: / number of charges |
'
+ +' store: | [ add / any / change / none ] | Defaults to none (or not specified). Specifies flexibility of spell storing |
'
+ +' | add | Allows the character to add additional stored spells to the item (up to any level limit) but stored spells can only be replaced by the same |
'
+ +' | change | Allows the character to change what spell is stored in each slot (within any level limit), but not to add spells to additional slots |
'
+ +' | any | Allows the character to both add additional spells and to change the currently stored spells (up to any level limit). |
'
+ +'
'
+ +'
Merging another item definition: Using the Roll20 standard syntax of %{...|...} to merge in another item data definition saves duplicating text that has already been written. The name before the \'pipe\' character (\'|\') is the name of the database to get the merged specification from - this can be a database held in memory by the APIs or a character sheet database: the APIs will work this out. The APIs only recognise the first Specs=[...] and Data=[...] they find, so these are presented in this definition before the %{...|...}. On the contraty, when displaying the template to a player, later {{ xxx=... }} with the same xxx will overwrite earlier ones, so the differences in the description for this particular item are placed after the %{...|...}.
'
+ +'
3.4 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).
'
+ +'
'
+ +'
4. 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.
'
+ +'
'
+ +'
5. 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.
'
+ +'
'
+ +'
6. Specs & Data field values
'
+ +'
Below are lists of the current possible values for the item database Ability macro sections.
'
+ +'
6.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) 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(b) 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 |
'
+ +' Protection-[item] | Any item (other than clothing or a 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(c) 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(d) 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 | '
+ +' AC Data | '
+ +'
'
+ +' '
+ +' w: | < text > | \'-\' | Name to be displayed | | X | 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 | X |
'
+ +' n: | # [ / # ] | 1 | Attacks per round | | | | X | X | X | | X | X | |
'
+ +' st: | < text > | \'\' | Item type to display | | X | X | X | X | X | X | X | | X |
'
+ +' hide: | [hide / nohide] | \'\' | Hidden item status | | X | X | X | X | X | X | X | | X |
'
+ +' rev: | [manual / view / use] | \'\' | Hidden item reveal trigger | | X | X | X | X | X | X | X | | X |
'
+ +' sz: | [ t / s / m / l / h ] | \'\' | Size of item | | | | X | 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 | X |
'
+ +' rules: | [+/-][rule] | ... | 0 | Save / Check rules | | | | X | X | X | X | X | | X |
'
+ +' svXXX: | [=][+/-]# | 0 | Save / Check mod | | | | X | X | X | X | X | | X |
'
+ +' on: | command | \'\' | Cmd to execute when worn | | | | X | X | X | X | | | |
'
+ +' off: | command | \'\' | Cmd to execute when removed | | | | X | X | X | X | | | |
'
+ +' ns: | # | 0 | Number of stored spells & powers defined for item | | | X | 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 | | 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 | | 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 | 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 | 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 | |
'
+ +' learn: | [ 0 | 1 ] | 0 | Learnable stored spells | | | 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.03,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Class & Race Database Help v2.03'
+ +'
'
+ +''
+ +'
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 sav for all saving throws, str, dex, con, int, wis, chr or atr for all character attributes, or all for everything, 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 best modifier of that type from all items preceeded by an 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.
'
+ +'
It is also possible to specify rules for when the specified saving throw/ability check modifiers are valid. These are specified by including the data tag rules:. See the Magic Database Help handout for more information on rules:.
'
+ +'
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 |
'
+ +' specmu: | [ 0 | 1 ] | (not shown above) a flag signifying whether a non-standard wizard-type spellcaster is a specialist or not, granting the extra spell per level if \'1\' |
'
+ +'
'
+ +'
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 |
'
+ +' age: | <#> | (not shown above) the character age value at which they will gain this power (used for e.g. dragons). The age value is stored in @{selected|age|max} |
'
+ +' 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 | roll,text,[speed],[type],[+tohit] | specification for creature innate attack 1 |
'
+ +' attk2 | roll,text,[speed],[type],[+tohit] | specification for creature innate attack 2 |
'
+ +' attk3 | roll,text,[speed],[type],[+tohit] | 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. Note: values in square brackets are optional and the brackets should not be included if used.
'
+ +'
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 |
'
+ +'
'
+ +'
4.2 Creatures with Spell-Casting Ability
'
+ +'
It is possible to give spell-casting creatures spells as powers - just specify the number per day as 1, and you can even use the MU-[Spell-Name] or PR-[spell-name] syntax as the power name to specify the spells to use (as shown in the Vampire above). However, for larger numbers of spells, and/or to grant random spells, an additional syntax is available:
'
+ +'
&{template:RPGMdefault}{{}}RaceData=[w:Frost Giant Witch Doctor,sps:any,cattr:cl=pr:frost-giant-shaman/mu:frost-giant-witch-doctor|lv=7/3,ns:2],[cl:MU,lv:1,w:random|random|random|Detect-Magic],[cl:MU,lv:2,w:random|ESP|Mirror-Image|random|random]{{}}Specs=[Frost-Giant-Witch-Doctor,CreatureRace,2H,Frost-Giant-AC0]{{}}%{Race-DB-Creatures|Frost-Giant-AC0}{{name= Witch Doctor}}{{Section3=**Witch Doctor:** This Frost Giant is a Witch Doctor that can cast spells of a number of wizard spells, and priest spheres of magic:*healing, charm, protection, divination*, or *weather*}}{{desc6=**Frost Giant Witch Doctor:** There is a 20% chance that any band of frost giants will have a shaman (80%) or witch doctor (20%). If the group is led by a jarl, there is an 80% chance for a spell caster. Frost giant shamans are priests of up to 7th level. A shaman can cast normal or reversed spells from the *healing, charm, protection, divination*, or *weather* spheres. Frost giant witch doctors are priest/wizards of up to 7th/3rd level; they prefer spells that can bewilder and confound other giants. Favorite spells include: *unseen servant, shocking grasp, detect magic, ventriloquism, deeppockets, ESP, mirror image,* and *invisibility*.}}
'
+ +'
This Witch Doctor has a number of spells specified to be in their spellbook by using the RaceData extension data sets:
'
+ +'
[cl:MU,lv:1,w:random|random|random|Detect-Magic],[cl:MU,lv:2,w:random|ESP|Mirror-Image|random|random]
'
+ +'
The cl:MU
specifies that this data set specifies spells for the spellbook, and the lv:#
specifies the level of spells. The w: string then defines the spell names, separated by pipes \'|\'. These names must be the same as those given in the spells databases (which can be listed using the GMs [Token Setup] / [Add Spells & Powers] dialog), or can be \'random\'. Specifying \'random\' will do what it says on the tin - a random spell will be chosen from all available spells at that level. If more than one spell is stated as \'random\' there is a chance that the same one will come up twice - the APIs will allow this.
'
+ +'
If a spellbook is specified for a creature in this way, it must be of a class that can cast spells or it will not be able to use them. The creature\'s level as a spellcaster will determine how many spells can be memorised at each level, regardless of how many are given in the spellbooks.
'
+ +'
Also, if spellbooks are specified like this the API will automatically memorise spells, selecting spells from the list at random up to the correct number for the creature\'s level. If a creature can cast Wizard spells and no spellbooks are specified, random spells will be memorised from all possible wizard spells that are valid for the schools that caster can cast. The GM (or other controlling player) can always use the Spells Menu to memorise different spells, and the GM can use the [Token Setup] / [Add Spells & Powers] dialog to change the spellbooks.
'
+ +'
If the creature can cast Priest spells, the creature will be granted a spellbook of all priest spells that are valid for the spheres it can cast, and random spells from this list automatically memorised from this list. The specification can override this behaviour by specifying particuler priest spells to have in the spellbook at a specific level using [cl:PR,lv:#,w:....]
. Alternatiely, if the w: is followed by an empty string e.g. [cl:PR,lv:#,w:]
, then the correct number of random priest spells will be memorised at each level, but only those memorised spells will be written to the spellbook. An example of this is for dragons, as according to the Monsterous Manual they only know an exclectic mix of spells they have picked up as they age and are not granted spells by a god.
'
+ +'
4.3 Complex Creatures with Multiple Forms
'
+ +'
Some creatures, such as Dragons, have multiple forms and also vary within a single form. For example, a Dragon can be Red, Blue, White, Gold, Silver, Crystal, ... etc. Not only that, but each of these dragons\' powers grow with age from Hatchling through Juvenile, Adulthood, to Venerable, Wyrm & Great Wyrm. Rather than create a definition for each age and colour combination (which would result in 180 definitions just for the standard dragons!) it is possible to add a query presented to the GM when selecting the type of creature to drag & drop. This query can specify data to be factored into calculations in the RaceData specification dependent on the selection made.
'
+ +'
&{template:RPGMdefault}{{title=Red}}{{name=Dragon}}Specs=[Dragon,DragonRace,2H,Creature]{{subtitle=Dragon}}RaceData=[w:Red Dragon, query:What Age?|Hatchling%%1%%-6|Very Young%%2%%-4|Young%%3%%-2|Juvenile%%4%%0|Young Adult%%5%%1|Adult%%6%%2|Mature Adult%%7%%3|Old%%8%%4|Very Old%%9%%5|Venerable%%10%%6|Wyrm%%11%%7|Great Wyrm%%12%%8, align:CE, ac:none, cattr:int=15:16|mov=9|fly=30C|jump=3|ac=1-??1|age=??0:??1|hd=(11+??1)d8r1|mr=(v(^((??1-4);0);1)*??1*5)|cl=mu:red-dragon/pr:red-dragon|lv=8+??1/8+??1|spellsp=1|thac0=11-??1|tohit=??2|dmg=??1|size=G|attk1=1d10:Claw x 2 or Claw+Kick:0:S|attk2=3d10:Bite:0:P|attk3=2d10:Tail Swipe:0:B|attkmsg=Remember powers such as *Dragon Fear; Wing Buffet; Snatch; Plummet;* and *Spell Casting*$$Remember powers such as *Dragon Fear; Wing Buffet; Snatch; Plummet;* and *Spell Casting*$$\lbrak;Show the radius\rbrak;\lpar;!rounds ~~aoe `{selected¦token_id}¦arc180¦0¦80¦160¦red\rpar; then up to \lbrak;\lbrak;`{selected¦age|max}\rbrak;\rbrak; opponents in the area take damage and Save vs. Petrification with the penalty shown below or be \lbrak;Stunned\rbrak;\lpar;!rounds ~~target area¦`{selected¦token_id}¦`{target¦Select the stunned creature¦token_id}¦Stunned¦\lbrak;[1+1d4]\rbrak;¦-1¦Stunned by a dragon tail slap¦back-pain\rpar; for 1d4+1 rounds., spattk:*Dragon Fear; Wing Buffet; Snatch; Plummet;* and *Spell Casting*, spdef:Magic resistance \lbrak;\lbrak;({ { { {(@{selected|age|max}-4)},{0} }kh1}, {1} }kl1) * (@{selected|age|max}+1) * 5\rbrak;\rbrak;%, ns:1],[cl:PW,w:MU-Affect-Normal-Fires,pd:3,sp:1],[cl:PW,w:MU-Pyrotechnics,pd:3,sp:1],[cl:PW,w:PR-Heat-Metal,pd:1,sp:1],[cl:PW,w:MU-Suggestion,pd:1,sp:1],[cl:PW,w:MU-Hypnotism,pd:1,sp:1],[cl:PW,w:Detect-Gems-Kind+Number,pd:3,sp:1],[cl:PW,w:Red-Dragon-Breath,pd:-1,sp:1],[cl:PW,w:PW-Snatch,lv:14,pd:-1,sp:0],[cl:PW,w:PW-Plummet,pd:-1,sp:0],[cl:PW,w:PW-Wing-Buffet,lv:14,pd:-1,sp:0],[cl:PW,w:PW-Stall,pd:-1,sp:0],[cl:PW,w:PW-Dragon-Fear,lv:14,pd:-1,sp:0],[cl:PR,lv:1,w:],[cl:PR,lv:2,w:]{{Section=**Attributes**}}{{Intelligence=Exceptional (15-16)}}{{AC=Varies with age, adult red dragon is AC -5}}{{Alignment=Chaotic Evil}}{{Move=9, FL 30(C), Jump 3}}{{Hit Dice=Varies with age, adult red dragon is 15 HD}}{{THAC0=Varies with age, adult red dragon is 5}}{{Section1=**Attacks:** ToHit and damage bonus varies with age, adult red dragon is +2 and +6. 2 x Claws for 1d10 HP each, possibly with 1 or 2 kicks for 1d10 each, bite for 3d10, and tail slap for 2d10 and possible *stun* within an area varying with age. Several other attacks possible - see *Powers*}}{{Languages=*Red Dragon* and *Dragon Common*, and 16% if hatchlings (+5% per age level) can perform universal communication with any intelligent creature}}{{Size=G, varies with age}}{{Life Expectancy=Possibly in excess of 1,000 years. Adult dragons are considered between 100 and 200 years old}}{{Section2=**Powers**}}{{Breath Weapon=A cone of flame, 90ft long, 5ft wide at dragon and spreading to 30ft wide. Damage varies by age from 2d10+1 to 24d10+12. Save vs. Breath Weapon to take half damage}}{{Fear=Can inspire fear in creatures that see the dragon: affect varies with the level / HD of the viewing creature.}}{{Spell Casting=Knows a number of random wizard and priest spells cast at a level from 10 to 21 varying with age. All spells are cast at a speed of 1 segment regardless of the spell}}{{Spell-like Powers=*Young* dragons can *Affect Normal Fires* x 3 per day, *Juveniles* gain *Pyrotechnics* x3 per day, *Adult* gains *Heat Metal* x 1 per day, *Old* gain *Suggestion* x 1 per day, *Very Old* gain *Hypnotism* x 1 per day, and *Venerable* gain *Detect Gems, Kind & Number* x 3 per day}}{{Special Attacks=*Snatch, Plummet, Stall*, and *Wing Buffet*}}{{Section4=**Special Advantages**}}{{Section5=Its a Dragon!}}{{Section6=**Special Disadvantages**}}{{Section7=None}}{{Section9=**Description**}}{{desc7=Dragons are an ancient, winged reptilian race. They are known and feared for their size, physical prowess, and magical abilities. The oldest dragons are among the most powerful creatures in the world.
Most dragons are identified by the color of their scales. All subspecies of dragons have 12 age categories, and gain more abilities and greater power as they age. Dragons range in size from several feet upon hatching to more than 100 feet, after they have attained the status of great wyrm. The exact size varies according to age and subspecies... }}
'
+ +'
In the case of dragons, this query asks the GM for the age to make the dragon, and sets two values based on the age to use in calculations (seen above in red). The query will be applied to all creatures of the Creature Database-Class (Specs definition field 2), in this case any DragonRace creature, even if the roll query is specified in the definition of only 1 such creature. Different roll queries can be specified for different Creature Database-Classes: you can make up your own db-classes to differentiate them.
'
+ +'
The query specification in the Data section has the following syntax:
'
+ +'
query:What Age?|Hatchling%%1%%-6|Very Young%%2%%-4|Young%%3%%-2|Juvenile%%4%%0|Young Adult%%5%%1|Adult%%6%%2|Mature Adult%%7%%3|Old%%8%%4|Very Old%%9%%5|Venerable%%10%%6|Wyrm%%11%%7|Great Wyrm%%12%%8
'
+ +'
If you are familiar with Roll20 Roll Queries, you will note that the ?{...} has been left out: only the text between the braces is defined. This text starts with the query text to be presented to the GM - "What Age?". Possible answers are then specified, separated by pipes \'|\'. Each answer has text followed by values separated by double-percents \'%%\'. The text will be displayed in the roll query to the GM to select the option. The percent-separated values will be returned by the query, including the text as the first value.
'
+ +'
It is then possible to refer to the returned values in the RaceData specification using the syntax ??#
, where # is the zero-based number of the value - ??0 is the text of the option selected, ??1 the next value, ??2 the value after that, etc. An example of this is given in the new age=??0:??1
data specification in red above, which will set the character sheet "age" field to the text of the dragon\'s age selected by the GM, and the sheet "age|max" field to the ??1 parameter, which is the "age value" of that age of dragon.
'
+ +'
It is possible to do simple maths using these values and others in the data specification. The API supports plus (+), minus (-), times (*), divide (/), left & right parenthesis (()), max (^(...;...)), min (v(...;...)), dice rolls (#d#+#r#), and ranges (#:#). These operators can be combined in simple ways - to be honest, I\'ve not tested all possible combinations - keep it simple and it should work! An example is the calculation for magic resistance:
'
+ +'
mr=(v(^((??1-4);0);1)*??1*5)
'
+ +'
The order of calculation is:
'
+ +'
- the two instances of ??1 will be replaced by the first value after the selected text in the roll query,
'
+ +'- then the parentheses that hold numbers are calculated (??1-4),
'
+ +'- then any ranges are resolved by rolling a number in the range (none here),
'
+ +'- next dice rolls are made (none here),
'
+ +'- then the max & min are resolved and
'
+ +'- the final parentheses calculated.
'
+ +'
Ranges: These are specified with two numbers separated by a colon, thus ##:##
. E.g. 3:18 - The API will attempt to roll any range by using the Roll20 dice roller, with 3 dice if possible (so that standard attribute rolls of NPCs and creatures are as close to real as possible). Thus, 3:18 is rolled using 3d6, 6:15 will be 3d4+3, 5:17 is 3d5+2. If a range is too small or cannot be done with 3 dice, 2 or 1 will be used instead, so 2:4 will be 1d3+1, 15:16 will be 1d2+14 etc. If you want more control, specify a particular dice roll.
'
+ +'
Dice Rolls: can be specified using the syntax #d#+#r#
or #d#-#r#
: all parts except the #d# are optional. The r# specifies a re-roll number - if any dice roll is equal to or less than the r# number, that dice alone will be rerolled until the value is higher. Note: The Hit Dice specification (hd=) can use a format like #d#
or #d#+#
or #d#+#r#
(the plus can be a minus), or can be extended to #d#+#d#r#
(i.e. the roll modifier can be a dice roll itself) - but the reroll value always applies to the main dice roll. Avoid other maths for the Hit Dice value, but ??# substitutions and maths on the number of dice are possible e.g. (??1+9)d8+??2r2
is valid.
'
+ +'
Min & Max: The operators ^ (caret - max) and v (lower-case V - min) can be used with the syntax ^(#;#;#)
or v(#;#;#;#)
(any number of values is valid) and will evaluate to the maximum or minimum value respectively. Note that a semi-colon separator \';\' is used rather than a comma.
'
+ +'
So now it can be seen that the Magic Resistance calculation above will resolve to 0 if the ??1 value is 4 or less, or (5 times ??1) if ??1 is 5 or more. The combination of the Roll Query, values set by the answer to it, and the simple maths engine can provide powerful results.
'
+ +'
Note: semi-colons are used for min & max seperators, and square brackets avoided for calculations, so that Roll20 calculations are not inappropriately triggered when the Roll Templates are displayed and so that these calculations can be passed in API calls. Use these forms of maths in creature definition data specifications, and not Roll20 calculations, to avoid issues. Roll20 calculations can be used inside {{...}} parts of Roll Templates as these will never be encountered by the API management functions, including in API button calls.
'
+ +'
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.05,
+ avatar:'https://s3.amazonaws.com/files.d20.io/images/257656656/ckSHhNht7v3u60CRKonRTg/thumb.png?1638050703',
+ bio:''
+ +'Attacks Database Help v1.05'
+ +'
'
+ +''
+ +'
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 ^^monsterDmgL^^ | 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},
+ INIT: {prefix:'InitMagic_', tableDef:fields.InitMagic_table},
+ SAVES: {prefix:'SaveMod_', tableDef:fields.SaveMod_table},
+// WEAP: {prefix:'Weap_', tableDef:fields.Weap_table},
+ MONWEAP:{prefix:'MonWeap_', tableDef:fields.MonWeap_table},
+ ALTWIZ: {prefix:'AltSpells_', tableDef:fields.AltWizSpells_table},
+ ALTPRI: {prefix:'AltSpells_', tableDef:fields.AltPriSpells_table},
+ ALTPWR: {prefix:'AltPowers_', tableDef:fields.AltPowers_table},
+ });
+ const miTypeLists = Object.freeze({
+ miscellaneous: {type:'miscellaneous',field:fields.ItemMiscList},
+ protectioncloak:{type:'miscellaneous',field:fields.ItemMiscList},
+ protectionboots:{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},
+ barding: {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},
+ equipment: {type:'equipment',field:fields.ItemEquipList},
+ light: {type:'equipment',field:fields.ItemEquipList},
+ attackmacro: {type:'attack',field:fields.ItemAttacksList},
+ style: {type:'style',field:fields.ItemWeaponList},
+ ability: {type:'ability',field:fields.ItemAbilitiesList},
+ trap: {type:'trap',field:fields.ItemTrapsList},
+ lock: {type:'lock',field:fields.ItemLocksList},
+ });
+ var clTypeLists = {
+ warriorclass: {type:'warrior',field:fields.ClassWarriorList,query:''},
+ warriorhrclass: {type:'warrior',field:fields.ClassWarriorList,query:''},
+ warriorkitclass:{type:'warrior',field:fields.ClassWarriorList,query:''},
+ wizardclass: {type:'wizard',field:fields.ClassWizardList,query:''},
+ wizardhrclass: {type:'wizard',field:fields.ClassWizardList,query:''},
+ wizardkitclass: {type:'wizard',field:fields.ClassWizardList,query:''},
+ priestclass: {type:'priest',field:fields.ClassPriestList,query:''},
+ priesthrclass: {type:'priest',field:fields.ClassPriestList,query:''},
+ priesthoodclass:{type:'priest',field:fields.ClassPriestList,query:''},
+ priestkitclass: {type:'priest',field:fields.ClassPriestList,query:''},
+ rogueclass: {type:'rogue',field:fields.ClassRogueList,query:''},
+ roguehrclass: {type:'rogue',field:fields.ClassRogueList,query:''},
+ roguekitclass: {type:'rogue',field:fields.ClassRogueList,query:''},
+ psionclass: {type:'psion',field:fields.ClassPsionList,query:''},
+ psionhrclass: {type:'psion',field:fields.ClassPsionList,query:''},
+ psionkitclass: {type:'psion',field:fields.ClassPsionList,query:''},
+ creatureclass: {type:'creature',field:fields.ClassCreatureList,query:''},
+ humanoidrace: {type:'humanoid',field:fields.RaceHumanoidList,query:''},
+ humanoidhrrace: {type:'humanoid',field:fields.RaceHumanoidList,query:''},
+ humanoidkitrace:{type:'humanoid',field:fields.RaceHumanoidList,query:''},
+ humanoidcreature:{type:'creature',field:fields.RaceCreatureList,query:''},
+ creaturerace: {type:'creature',field:fields.RaceCreatureList,query:''},
+ creaturehrrace: {type:'creature',field:fields.RaceCreatureList,query:''},
+ creaturekitrace:{type:'creature',field:fields.RaceCreatureList,query:''},
+ container: {type:'container',field:fields.ContainerList,query:''},
+ };
+ 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:['']},
+ magic: {type:'',field:['']},
+ innatemagic: {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,'MU'],
+ [fields.Priest_class,fields.Priest_level,'PR'],
+ [fields.Fighter_class,fields.Fighter_level,'F'],
+ [fields.Rogue_class,fields.Rogue_level,'RO'],
+ [fields.Psion_class,fields.Psion_level,'PS'],
+ [fields.Fighter_class,fields.Monster_hitDice,'M']
+ ];
+ var classMap = [[fields.ClassMap1,fields.LevelMap1],[fields.ClassMap2,fields.LevelMap2],[fields.ClassMap3,fields.LevelMap3]];
+
+ 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],
+ ];
+
+ var saveFormat = {
+ Saves: {
+ Paralysis: {save:fields.Saves_paralysis,mod:fields.Saves_modParalysis,mon:fields.Saves_monParalysis,index:0,roll:'1d20',tag:'par'},
+ Poison: {save:fields.Saves_poison,mod:fields.Saves_modPoison,mon:fields.Saves_monPoison,index:0,roll:'1d20',tag:'poi'},
+ Death: {save:fields.Saves_death,mod:fields.Saves_modDeath,mon:fields.Saves_monDeath,index:0,roll:'1d20',tag:'dea'},
+ Rod: {save:fields.Saves_rod,mod:fields.Saves_modRod,mon:fields.Saves_monRod,index:1,roll:'1d20',tag:'rod'},
+ Staff: {save:fields.Saves_staff,mod:fields.Saves_modStaff,mon:fields.Saves_monStaff,index:1,roll:'1d20',tag:'sta'},
+ Wand: {save:fields.Saves_wand,mod:fields.Saves_modWand,mon:fields.Saves_monWand,index:1,roll:'1d20',tag:'wan'},
+ Petrification: {save:fields.Saves_petrification,mod:fields.Saves_modPetrification,mon:fields.Saves_monPetri,index:2,roll:'1d20',tag:'pet'},
+ Polymorph: {save:fields.Saves_polymorph,mod:fields.Saves_modPolymorph,mon:fields.Saves_monPolymorph,index:2,roll:'1d20',tag:'pol'},
+ Breath: {save:fields.Saves_breath,mod:fields.Saves_modBreath,mon:fields.Saves_monBreath,index:3,roll:'1d20',tag:'bre'},
+ Spell: {save:fields.Saves_spell,mod:fields.Saves_modSpell,mon:fields.Saves_monSpell,index:4,roll:'1d20',tag:'spe'},
+ },
+ Attributes: {
+ Strength: {save:fields.Strength,mod:fields.Saves_modStrength,roll:'1d20',tag:'str'},
+ Constitution: {save:fields.Constitution,mod:fields.Saves_modConstitution,roll:'1d20',tag:'con'},
+ Dexterity: {save:fields.Dexterity,mod:fields.Saves_modDexterity,roll:'1d20',tag:'dex'},
+ Intelligence: {save:fields.Intelligence,mod:fields.Saves_modIntelligence,roll:'1d20',tag:'int'},
+ Wisdom: {save:fields.Wisdom,mod:fields.Saves_modWisdom,roll:'1d20',tag:'wis'},
+ Charisma: {save:fields.Charisma,mod:fields.Saves_modCharisma,roll:'1d20',tag:'chr'},
+ },
+ Checks: {
+ Open_Doors: {save:fields.OpenDoors,mod:fields.Saves_modOpenDoors,roll:'1d20',tag:'opd'},
+ Bend_Bars: {save:fields.BendBars,mod:fields.Saves_modBendBars,roll:'1d100',tag:'bbr'},
+ System_Shock: {save:fields.SystemShock,mod:fields.Saves_modSystemShock,roll:'1d100',tag:'sys'},
+ Resurrection: {save:fields.ResSurvive,mod:fields.Saves_modResSurvive,roll:'1d100',tag:'res'},
+ Learn_Spell: {save:fields.LearnSpell,mod:fields.Saves_modLearnSpell,roll:'1d100',tag:'lsp'},
+ Spell_Failure: {save:fields.SpellFail,mod:fields.Saves_modSpellFail,roll:'1d100',tag:'spf'},
+ },
+ };
+
+ const rogueSkills = {
+ pickpockets: {name:'Pick_Pockets',save:['ppt','current'],roll:'1d100',tag:'pp',factors:['ppb','ppr','ppd','ppk','ppa','ppm','ppl'],gmrolls:true,success:'You got the item!',failure:'You can try again, unless you are caught!'},
+ openlocks: {name:'Open_Locks',save:['olt','current'],roll:'1d100',tag:'ol',factors:['olb','olr','old','olk','ola','olm','oll'],gmrolls:false,success:'Click! After [[1d10]] rounds the lock opens',failure:'Hard luck. [[1d10]] rounds wasted. You can try once per experience level'},
+ findtraps: {name:'Find_Traps',save:['rtt','current'],roll:'1d100',tag:'rt',factors:['rtb','rtr','rtd','rtk','rta','rtm','rtl'],gmrolls:true,success:'After [[1d10]] rounds you know the general nature of any trap but not exact detail',failure:'[[1d10]] rounds go by. Try again at next level'},
+ removetraps: {name:'Remove_Traps',save:['rtt','current'],roll:'1d100',tag:'rt',factors:['rtb','rtr','rtd','rtk','rta','rtm','rtl'],gmrolls:true,success:'After [[1d10]] rounds you have successfully removed the trap',failure:'[[1d10]] rounds go by unsuccessfully. 96-00 triggers trap! Try again at next level'},
+ movesilently: {name:'Move_Silently',save:['mst','current'],roll:'1d100',tag:'ms',factors:['msb','msr','msd','msk','msa','msm','msl'],gmrolls:true,success:'Move at 1/3 rate. Gain -2 to surprise only if also unseen',failure:'Movement still reduced to 1/3'},
+ hideinshadows: {name:'Hide_in_Shadows',save:['hst','current'],roll:'1d100',tag:'hs',factors:['hsb','hsr','hsd','hsk','hsa','hsm','hsl'],gmrolls:true,success:'Does not work in darkness. Hidden only while motionless except small movements (draw weapon, drin potion etc). Cannot be seen with infravision except in darkness. "See Invisible" will see character',failure:'The character is not hidden'},
+ detectnoise: {name:'Detect_Noise',save:['dnt','current'],roll:'1d100',tag:'dn',factors:['dnb','dnr','dnd','dnk','dna','dnm','dnl'],gmrolls:true,success:'In silent surrounds & not wearing head-gear, sounds are heard',failure:'Even in silent surrounds & not wearing head-gear, nothing is heard'},
+ climbwalls: {name:'Climb_Walls',save:['cwt','current'],roll:'1d100',tag:'cw',factors:['cwb','cwr','cwd','cwk','cwa','cwm','cwl'],gmrolls:false,success:'Can climb up to 100ft in 10 rounds, then roll again',failure:'Can\'t start or is stuck where currently is. Try again somewhere significantly different'},
+ readlanguages: {name:'Read_Languages',save:['rlt','current'],roll:'1d100',tag:'rl',factors:['rlb','rlr','rld','rlk','rla','rlm','rll'],gmrolls:false,success:'Can understand about value2% of the meaning',failure:'Not understandable at all. Try again at next level'},
+ legendlore: {name:'Legend_Lore',save:['ibt','current'],roll:'1d100',tag:'ll',factors:['ibb','ibr','ibd','ibk','iba','ibm','ibl'],gmrolls:false,success:'In [[1d10]] rounds of examination you learn some general information',failure:'[[1d10]] rounds of examination reveal nothing'},
+ };
+ const thiefSkillFactors = ['Base','Race','Dexterity','Kit','Armour','Magic','Level'];
+
+ var 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],
+ [fields.Monster_class,fields.Monster_level,-2],
+ ];
+ 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},
+ };
+ const xlateSave = {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'};
+ 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 = false;
+ const stdDB = ['mu_spells_db','mu_spells_db_l1','mu_spells_db_l2','mu_spells_db_l3','mu_spells_db_l4','mu_spells_db_l5','mu_spells_db_l6','mu_spells_db_l7','mu_spells_db_l8','mu_spells_db_l9','mu_spells_db_custom','pr_spells_db_l1','pr_spells_db_l2','pr_spells_db_l3','pr_spells_db_l4','pr_spells_db_l5','pr_spells_db_l6','pr_spells_db_l7','pr_spells_db_custom','powers_db','mi_db','mi_db_custom','mi_db_ammo','mi_db_armour','mi_db_equipment','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_a_e','race_db_creatures_f_j','race_db_creatures_k_o','race_db_creatures_p_t','race_db_creatures_u_z','styles_db','abilities_db'];
+ const waitMsgDiv = '
' ;
+ const errorMsgDiv = '
' ;
+
+ 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*?(?:,\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*?(?:,\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 reName = /[\[,]\s*?w:\s*[^\],]+?[,\]]/im;
+ const reLevel = /[\[,]\s*?lv:(\d+?)[,\s\]]/im;
+ const reClassData = /}}\s*?ClassData\s*?=(.*?){{/im;
+ const reClassRaceData = /}}\s*?(?:Class|Race)Data\s*?=.*?{{/im;
+ const reSpellData = /}}\s*?SpellData\s*?=(.*?){{/im;
+ const reRepeatingTable = /^(repeating_.*)_\$(\d+)_.*$/;
+ const reNumSpellsData = /}}[\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, "&"],
+ [/\\lpar;?/g, "("],
+ [/\\rpar;?/g, ")"],
+ [/\\cr;?/g, "
"],
+ [/&&/g, "/"],
+ [/%%/g, "%"],
+ [/\\comma;?/g, ","],
+ [/\\fs;?/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.4) 3px 3px',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 DBindex;
+ var classesParsed = false;
+ var magicList = {};
+ var RPGMap = {};
+ var apis = {magic:false,attk:false,init:false};
+ var lastMsg = [];
+ var doneRNmsg = false;
+ var waitList = {};
+ var msg_orig = {};
+ var showMoreObj = {};
+
+ 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;
+ }
+
+ /*
+ * Clear any waiting timer action saved in the playerConfig
+ */
+
+ var clearWaitTimer = function(pid) {
+ if (pid && waitList[pid]) {
+ clearTimeout(waitList[pid]);
+ waitList[pid] = undefined;
+ } else if (!pid) {
+ _.each(waitList,w=>clearTimeout(w));
+ waitList = {};
+ }
+ 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(waitMsgDiv+'You can read the latest **[Release Notes here]('+fields.journalURL+handoutIDs.RPGMReleaseNotes+')**, version '+handouts.RPGM_Release_Notes.version+' updated '+(new Date(lastUpdate*1000).toDateString())+'
');
+ }
+ }
+
+ 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() === (String(txt) || '').dbName();
+ }
+
+ class AbilityObj {
+ constructor( dBname, abilityObj, ctObj, source ) {
+ this.dB = dBname;
+ this.obj = (_.isUndefined(abilityObj) || !_.isArray(abilityObj) || abilityObj.length < 2) ? abilityObj : [_.clone(abilityObj[0]),_.clone(abilityObj[1])];
+ 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;
+ }
+ classes() {
+ /**
+ * Search a database object body for the object "class"
+ **/
+ let objType = [],
+ specs = this.obj[1].body.match(/}}\s*?specs\s*?=(.*?){{/im);
+ specs = specs ? [...('['+specs[0]+']').matchAll(reSpecClass)] : [];
+ for (let i=0; i < specs.length; i++) {
+ objType.push(specs[i][1]);
+ }
+ return _.uniq(objType.join('|').toLowerCase().split('|')).join('|');
+ }
+
+
+ }
+
+ class CharTable {
+ constructor( property, attrs, defaultVal ) {
+ if (!property || !isArray(property) || property.length < 2) throw new Error('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 new Error('Invalid character object in table constructor');
+ if (!table || !isArray(table) || table.length < 2) throw new Error('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 new Error('No table attribute supplied to addTable() for '+this.table[0]+', attrDef '+attrDef);
+ let rowName, index = 0, 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':'')),
+ orderMatcher=new RegExp(`^${this.table[0]}${this.col}_([-\\da-zA-Z]+)_`,(caseSensitive?'i':'')),
+ attrs=_.chain(findObjs({type:'attribute', characterid:this.character.id}))
+ .map((a)=>{
+ let orderKey = (a.get('name').match(orderMatcher)||['',''])[1];
+ if (orderKey && !createOrderKeys.includes(orderKey)) {
+ createOrderKeys.push(orderKey);
+ };
+ return {attr:a,match:a.get('name').match(attrMatcher)};
+ })
+ .filter((o)=>o.match)
+ .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) ? _.union(sortOrderKeys,this.sortKeys) : _.union(this.sortKeys,sortOrderKeys);
+ }
+ this[name].attrs=attrs;
+ if (_.isUndefined(this.values[attrDef[0]])) {
+ this.values[attrDef[0]] = Object.create({current:'',max:''});
+ }
+ this.values[attrDef[0]][attrDef[1]] = attrDef[2] || '';
+ } 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 = {};
+ _.each( fields, (elem,key) => {
+ if (key.startsWith(fieldGroup)
+ && ['current','max'].includes(String(elem[1]).toLowerCase())) {
+ rows[key]=elem;
+ };
+ });
+ _.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 new Error('No table attribute supplied to tableLookup() for '+this.table[0]+', attrDef '+attrDef);
+ var val, name = attrDef[0];
+ if (_.isUndefined(retObj)) {
+ retObj=false;
+ } else if (retObj === true) {
+ defVal=false;
+ }
+ if (_.isUndefined(defVal)) {
+ defVal=true;
+ }
+ if (this[name] && !_.isUndefined(index)) {
+ let property = (retObj === true) ? null : ((retObj === false) ? attrDef : retObj);
+ defVal = (defVal===false) ? (undefined) : ((defVal===true) ? this[name].defaultVal[attrDef[1]] : defVal);
+// if (!_.isUndefined(defVal)) defVal = String(defVal);
+ if (index>=0) {
+ let attrs = this[name].attrs,
+ sortOrderKeys = this.sortKeys;
+ if (index
{
+ if (_.isUndefined(elem.attrs)) return;
+ currentVal = (!rowVals || _.isUndefined(rowVals[key])) ? elem.defaultVal['current'] : rowVals[key]['current'];
+ maxVal = (!rowVals || _.isUndefined(rowVals[key])) ? elem.defaultVal['max'] : rowVals[key]['max'];
+ this.tableSet( [key,'current'], index, currentVal );
+ this.tableSet( [key,'max'], index, maxVal );
+ });
+ } else {
+ if (index > this.sortKeys.length) {
+ this.addTableRow( index-1, undefined );
+ }
+ let rowObjID = generateRowID();
+ let namePt1 = this.table[0]+this.col+'_'+rowObjID+'_';
+ let gotVals = !!rowVals && _.pairs(rowVals).length > 0;
+ _.each( list, (elem,key) => {
+ if (_.isUndefined(elem.attrs)) return;
+ rowObj = createObj( "attribute", {characterid: this.character.id, name: (namePt1+key+this.col)} );
+ if (!gotVals) {
+ newVal = _.isUndefined(this.values[key]) ? elem.defaultVal : this.values[key] ;
+ } else {
+ newVal = rowVals[key];
+ }
+ rowObj.set(newVal);
+ this[key].attrs[rowObjID] = rowObj;
+ this.sortKeys[index] = rowObjID;
+ });
+ }
+ return this;
+ }
+
+ /*
+ * Delete / remove a table row completely
+ */
+
+ delTableRow( index ) {
+
+ let rowObj, newVal, currentVal, maxVal, list = this;
+
+ let fieldGroup = this.fieldGroup;
+ if (!fieldGroup) throw new Error('undefined addTableRow fieldGroup');
+ if (index) index = parseInt(index);
+ if (_.isUndefined(index) || isNaN(index)) return this;
+
+ if ((index < 0) || ((index >= this.sortKeys.length) || _.isUndefined(this.tableLookup( fields[fieldGroup+'name'], index, false )))) return this;
+
+ _.each( list, (elem,key) => {
+ if (_.isUndefined(elem.attrs)) return;
+ elem.attrs[this.sortKeys[index]].remove();
+ _.omit(elem.attrs,this.sortKeys[index]);
+ });
+ this.sortKeys.splice(index,1);
+ return this;
+ };
+
+ /*
+ * A function to find the index of a matching entry in a table
+ */
+
+ tableFind( attrDef, val ) {
+
+ let findRE = _.isRegExp(val);
+ let findArray = _.isArray(val);
+ let findVal = !findRE && !findArray && (_.isString(val) || _.isNumber(val) || _.isBoolean(val));
+ if (!(findRE || findArray || findVal)) {
+ LibFunctions.sendError('Invalid search term "'+val+'" of type '+typeof val+' for tableFind while searching '+this.table[0]);
+ return undefined;
+ };
+ if (findVal) val = String(val).dbName() || '-';
+ if (findArray) val = val.map(v => v.dbName() || '-');
+ let property = attrDef[1];
+ let attrVal = LibFunctions.attrLookup( this.character, attrDef );
+ if ((this.table[1] < 0) && (findVal ? (val === String(attrVal.dbName() || '-')) :
+ (findRE ? (attrVal.search(val) >= 0) :
+ (findArray ? (val.includes(attrVal.dbName() || '-')) :
+ false )))) {
+ return -1;
+ }
+// log('tableFind: attrDef[0] = '+attrDef[0]+', _.size(this[attrDef[0]].attrs) = '+_.size(this[attrDef[0]].attrs)+', findRE = '+findRE+', findArray = '+findArray+', property = '+property);
+ let tableIndex = this.sortKeys.indexOf(
+ _.findKey(this[attrDef[0]].attrs, function( elem ) {
+ return (!elem ? false :
+ (findVal ? (val === (String(elem.get(property)).dbName() || '-')) :
+ (findRE ? String((elem.get(property)).search(val) >= 0) :
+ (findArray ? (val.includes(String(elem.get(property)).dbName() || '-')) :
+ false ))));
+ })
+ );
+ if (tableIndex < 0 && ((findVal && val === '-') || (findArray && val.includes('-')))) {
+ tableIndex = this.sortKeys.findIndex(k => (_.isUndefined(this[attrDef[0]].attrs[k]) || (!this[attrDef[0]].attrs[k].get(property))));
+ }
+ 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 new Error('No table attribute supplied to tableDefault() for '+this.table[0]+', attrDef '+attrDef);
+ if (_.isUndefined(val) || _.isNull(val)) val = this[attrDef[0]].defaultVal[attrDef[1]];
+ if (!this[attrDef[0]]) throw new Error('Invalid table attribute '+attrDef[0]+' supplied for '+this.table[0]);
+ _.each(this[attrDef[0]].attrs, obj => {
+ obj.set(attrDef[1],val);
+ });
+ return this;
+ }
+
+ /*
+ * Make a copy of the default values for the table
+ */
+
+ copyValues() {
+ let newValues = {};
+ _.each( this.values, (v,k) => newValues[k] = Object.create(v));
+ return newValues;
+ }
+
+ }
+
+ 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 ) {
+ if (!fieldGroup) return undefined;
+ 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, values ) {
+
+// let values = [new Set()];
+ if (_.isUndefined(values)) values = {};
+ let rows = _.filter( fields, (elem,f) => 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.classMap = classMap;
+ 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.rogueSkills = rogueSkills;
+ RPGMap.thiefSkillFactors = thiefSkillFactors;
+ RPGMap.reSpellSpecs = reSpellSpecs;
+ RPGMap.reWeapSpecs = reWeapSpecs;
+ RPGMap.reACSpecs = reACSpecs;
+ RPGMap.reClassSpecs = reClassSpecs;
+ RPGMap.reAttr = reAttr;
+ RPGMap.showMoreObj = showMoreObj;
+ 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, defValParam=true) {
+ let name, match,
+ property = attrDef[1];
+
+ if (!character || !character.id || (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];
+ }
+ let defVal = (defValParam === false ? undefined : (defValParam === true ? attrDef[2] : defValParam));
+ if (!_.isUndefined(defVal)) defVal = String(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,defValParam,!attrDef[1]);
+ } else {
+ let attrObj = findObjs({ type:'attribute', characterid:character.id, name:name}, {caseInsensitive: !caseSensitive});
+ if (!attrObj || attrObj.length == 0) {
+ 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 : String(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 (_.isUndefined(attrValue)) attrValue = _.isUndefined(attrDef[2]) ? '' : attrDef[2];
+ 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, db, spells, items, objIndex, abilityName, action,
+ trueAbilityName = (trueAbility || '').dbName(),
+ source = 'charDB',
+ notFound = false,
+ abilityObj = [],
+ ctObj = [],
+ rDB = rootDB.toLowerCase().replace(/-/g,'_');
+
+ var getTypes = function( body ) {
+ let objType = [],
+ specs = body.match(/}}\s*?specs\s*?=(.*?){{/im);
+ specs = specs ? [...('['+specs[0]+']').matchAll(reSpecClass)] : [];
+ for (let i=0; i < specs.length; i++) {
+ objType.push(specs[i][1]);
+ }
+ return _.uniq(objType.join('|').toLowerCase().split('|')).join('|');
+ };
+
+ if (_.isUndefined(DBindex[rDB])) {
+ for (db of _.keys(DBindex)) {
+ if (rDB.startsWith(db)) {
+ rDB = db;
+ 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.replace(/\s/g,'-')) });
+ 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 || !obj) {
+ source = 'apiDB';
+ db = 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');
+ db = getObj('character',charID).get('name');
+ spells = db.startsWith(fields.MU_SpellsDB) || db.startsWith(fields.PR_SpellsDB) || db.startsWith(fields.Powers_DB);
+ items = db.startsWith(fields.MagicItemDB);
+ abilityObj[0] = obj;
+ action = obj.get('action');
+ ct = !ct ? getObj('attribute',objIndex[1]) : ct[0];
+ abilityObj[1] = {name:obj.get('name'),
+ type:getTypes(action),
+ ct:(!ct ? 0 : ct.get('current')),
+ charge:(!ct || spells ? 'uncharged' : ct.get('max')),
+ cost:(!ct || items ? '0' : ct.get('max')),
+ body:action};
+ ctObj = [ct,abilityObj[1].ct];
+ };
+// if (!notFound && !isGM) abilityObj[1].body = abilityObj[1].body.replace(/{{\s*?Looks Like\s*=.*?}}/img,'');
+ return new AbilityObj( db, abilityObj, ctObj, source );
+ }
+
+ /*
+ * Create or update an ability on a character sheet
+ */
+
+ LibFunctions.setAbility = function( charCS, abilityName, abilityMacro, actionBar=false ) {
+
+ if (!charCS) {log('setAbility error: invalid character sheet');return;}
+ abilityName = !abilityName ? '-' : abilityName.hyphened();
+ var abilityObj = findObjs({type: 'ability',
+ characterid: charCS.id,
+ name: abilityName},
+ {caseInsensitive:true});
+ if (!abilityObj || abilityObj.length == 0 || !abilityObj[0] || abilityObj[0].get('name') !== abilityName) {
+ 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) return;
+ if (!args[0] && selected && selected.length) {
+ args[0] = selected[0]._id;
+ }
+ if (args.length < 3) {
+ LibFunctions.sendError('Incorrect RPGMaster command syntax',msg_orig[senderId]);
+ return;
+ }
+ if ((charCS = LibFunctions.getCharacter(args[0]))) args.unshift('standard');
+ var cmd = (args[0] || 'standard').toLowerCase(),
+ tokenID = args[1],
+ db = args[2],
+ ability = args[3],
+ diceRoll1 = args[4] || '',
+ diceRoll2 = args[5] || '',
+ targetID = args[6] || '',
+ charCS = LibFunctions.getCharacter(tokenID),
+ targetToken = getObj('graphic',targetID),
+ targetCS = (targetToken ? getObj('character',targetToken.get('represents')) : undefined),
+ isView = cmd.includes('view'),
+ abObj, abilityMacro;
+
+ var diceRoll = function( rollTxt ) {
+ if (!rollTxt) return randomInteger(20);
+ var retVal = rollTxt.match(/\d+d\d+/i);
+ retVal = (!retVal) ? parseInt((rollTxt.match(/\((\d+)\)/) || rollTxt.match(/(\d+)/) || [0,randomInteger(20)])[1]) : '[['+retVal+']]';
+ return retVal;
+ };
+
+ if (!charCS) {
+ LibFunctions.sendError('The token identified does not represent a character sheet',msg_orig[senderId]);
+ return;
+ }
+
+ if (db.toLowerCase().includes('-db')) {
+ abObj = LibFunctions.getAbility( db, ability, charCS );
+ if (!abObj.obj) {
+ LibFunctions.sendError(('The provided ability does not exist in any '+db+' database'),msg_orig[senderId]);
+ return;
+ }
+ abilityMacro = abObj.obj[1].body;
+ } else {
+ var abilityCS = findObjs({type:'character',_id:db});
+ if (!abilityCS || !abilityCS.length) abilityCS = findObjs({type:'character',name:db}, {caseInsensitive: true});
+ if (abilityCS && abilityCS[0]) {
+ abObj = findObjs({type:'ability',characterid:abilityCS[0].id,name:ability}, {caseInsensitive: true});
+ }
+ if (!abObj || !abObj.length) {
+ LibFunctions.sendError(('Not found ability '+ability+' for character '+db),msg_orig[senderId]);
+ return;
+ }
+ abilityMacro = abObj[0].get('action');
+ }
+ diceRoll1 = diceRoll(diceRoll1);
+ diceRoll2 = diceRoll(diceRoll2);
+
+ 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+'|');
+ }
+ cmd = cmd.replace(/\-?view/,'');
+ if (isView && !state.MagicMaster.viewActions) abilityMacro = abilityMacro.replace(/(? LibFunctions.parseStr((LibFunctions.attrLookup( charCS, [fields.ItemVar[0]+name+'+'+row+'-'+w,'current'] ) || '').split('/')[v] || '');
+
+ 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.replace('$$','$$$$'));
+ } else {
+ abObj.obj[1].body = abObj.obj[1].body.replace(/%{([^\|]+?)\|([^}]+?)}/,'');
+ }
+ }
+ } while (extra && extraDef.obj);
+
+ trueName = (trueName || '').trim();
+ 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 + '}}';
+ }
+ }
+ while (reVars.test(abObj.obj[1].body)) abObj.obj[1].body = abObj.obj[1].body.replace(reVars,varRes);
+ 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;
+ var originalTxt = txt;
+ if (senderId && senderId.length) {
+ for (const playerId of senderId.split(',')) {
+ lastMsg[playerId] = arguments;
+ isGM = isGM || playerIsGM(playerId);
+ }
+ }
+
+ clearWaitTimer(senderId);
+
+ 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, showMore='', rowCols=row1col, rowFrame=row1 ) {
+ let content = '';
+ if (!_.isUndefined(txtObj.desc)) content += (rowCols[(j++)%2]+rowFrame+ txtObj.desc +showMore +endRow1+endRow1col);
+ for (let i=1; i<=9; ++i) {
+ if (!_.isUndefined(txtObj['desc'+i])) content += (rowCols[(j++)%2]+rowFrame+ txtObj['desc'+i] +endRow1+endRow1col);
+ };
+ return content;
+ };
+
+ const maxDiceRoll = function( diceRoll ) {
+ var rollData = diceRoll.match(/(\d+)d(\d+)/i)||fields.ToHitRoll.match(/(\d+)d(\d+)/i)||['1d20',1,20];
+ return {min:(parseInt(rollData[1])||1), max:((parseInt(rollData[1]) * parseInt(rollData[2]))||20)};
+ };
+
+ const RPGMattack = function( txt ) {
+
+ const arReplace = function( txt, ac ) {
+ let arAdj = txt.match(/([-+]?\d+)\[([\s\w\d]+?)=([-+\d\|]+?)\]/i);
+ if (!arAdj || !arAdj.length) return txt;
+ txt = arAdj[3].split('|')[arAdj[1]];
+ txt = '+-'.includes(txt[0]) ? txt : '+'+txt;
+ return '[['+(ac && ac.length ? ac : arAdj[1])+txt+' ['+txt+' ['+arAdj[2]+'] ] ]]';
+ }
+
+ const varReplace = function( str, field ) {
+ var value = '';
+ if (field) {
+ field = field.replace(/[-\s]/g,'_').toLowerCase();
+ value = (/^[-+]?[\d.]+/.test(field)|| _.isUndefined(txtObj[field])) ? parseFloat(field) : parseFloat(txtObj[field].match(/[-+]?[\d.]+/));
+ }
+ return value;
+ }
+
+ 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 toHitRoll = (txt.match(/specs=\[.*?(\d+d\d+),.*\]/im)||['',fields.ToHitRoll])[1];
+ const minMaxRoll = maxDiceRoll(toHitRoll);
+ const isMax = state.attackMaster.naturalRolls && !isNaN(dice_roll) && dice_roll >= minMaxRoll.max;
+ const isMin = state.attackMaster.naturalRolls && !isNaN(dice_roll) && dice_roll <= minMaxRoll.min;
+ const hasDescs = /{{\s*desc\d?\s*=/im.test(txt);
+ var crit = false;
+ var fumble = false;
+ _.defaults(txtObj,attkDefaults);
+ txtObj.target_sac = arReplace( txtObj.target_sac, txtObj.target_ac );
+ txtObj.target_pac = arReplace( txtObj.target_pac, txtObj.target_ac );
+ txtObj.target_bac = arReplace( txtObj.target_bac, txtObj.target_ac );
+ 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.ar_adjust || txtObj.target_ac != '' || txtObj.result || hasDescs) ? 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.ar_adjust) {
+ content += ((txtObj.target_ac != '' || txtObj.result || hasDescs) ? bodyFrame : lastBodyFrame)
+ +row1col[0]
+ + rowC + txtObj.ar_adjust + endRowC
+ +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);
+ crit = (crit_roll && (crit_roll <= dice_roll));
+ fumble = (fumble_roll && (fumble_roll >= dice_roll));
+ if (crit || fumble) {
+ content += ((txtObj.target_ac != '' || txtObj.result || hasDescs) ? 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 || ((isMax || isMin) && !(crit || fumble))) {
+ let result = isMax || crit;
+ if (txtObj.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;
+ }
+ if (state.attackMaster.weapRules.naturals) result = (result || isMax) && !isMin;
+ if (state.attackMaster.weapRules.criticals) result = (result || crit) && !fumble;
+ if (txtObj.successcmd && txtObj.successcmd.length && result) {
+ while (/%%[_\d\w\+-]+?%%/.test(txtObj.successcmd)) txtObj.successcmd = txtObj.successcmd.replace( /%%([_\d\w\+-]+?)%%/, varReplace );
+ _.each(txtObj.successcmd.split(' '),cmd => LibFunctions.sendAPI(LibFunctions.parseStr(cmd)));
+ } else if (txtObj.failcmd && txtObj.failcmd.length && !result) {
+ while (/%%[_\d\w\+-]+?%%/.test(txtObj.failcmd)) txtObj.failcmd = txtObj.failcmd.replace( /%%([_\d\w\+-]+?)%%/, varReplace );
+ _.each(txtObj.failcmd.split(' '),cmd => LibFunctions.sendAPI(LibFunctions.parseStr(cmd)));
+ };
+ }
+ };
+ content += (hasDescs ? bodyFrame : lastBodyFrame)
+ +rowResult[result ? 0 : 1]+rowC+''+ ((isMax || crit) ? 'Natural '+dice_roll : ((isMin || fumble) ? 'Natural '+dice_roll : (result ? 'Success' : 'Failure'))) +''+endRowC+endRowResult
+ +endBodyFrame;
+ }
+ if (hasDescs) {
+ content += lastBodyFrame
+ +addDescs(txtObj,1)
+ +endBodyFrame;
+ }
+ content += endOuterFrame;
+ return content;
+ };
+
+ const RPGMspell = function( txt, preamble ) {
+ const spellDefaults = {prefix:'', 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 showMore = /{{hide\d=/img.test(originalTxt);
+ const showLess = /{{desc\d=/img.test(originalTxt);
+ const txtRowID = generateRowID();
+ if (showMore || showLess) showMoreObj[txtRowID] = (preamble+'&{template:'+template+'}'+originalTxt.replace(/{{hide(\d)=/img,'{{reveal$1=').replace(/{{desc(\d)=/img,'{{hide$1=').replace(/{{reveal(\d)=/img,'{{desc$1=') );
+ const showMoreButton = (showMore || showLess) ? (' *show '+(showMore ? 'more' : 'less')+'...*') : '';
+ const hasDescs = !isLooksLike && /{{\s*desc\d?\s*=/im.test(txt);
+ var content = outerFrame
+ +headerFrame
+ +header2+ (!isLooksLike ? txtObj.prefix : '')+' '+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 +showMoreButton +endRow2+endRow2col
+ +addDescs(txtObj,++k,'',row2col,row2)
+ ) : '');
+ +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, preamble, isShowMore=true ) {
+
+ var value1, value2;
+
+ const resultTest = function( t ) {
+ let result = false;
+ const test = t.match(/([\w\s_.+-]+?|[-+]?[\d.]+?)((?:<=|>=|<|>|=|<>|!=))(.+)/);
+ if (test) {
+ value1 = (/^[-+]?[\d.]+/.test(test[1])|| _.isUndefined(txtObj[test[1]])) ? parseFloat(test[1]) : parseFloat(txtObj[test[1]].match(/[-+]?[\d.]+/));
+ 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;
+ }
+ }
+ return result;
+ };
+
+ const rollVal = (m,v) => LibFunctions.evalAttr(v);
+
+ const defDefaults = {prefix:'', title:'', name:'', success:'', failure:''};
+ const txtObj = _.object([...txt.replace(/[\r\n]/g,'').matchAll(/\{\{(.+?)=(.*?)\}\}/g)].map(v => v.slice(1)));
+ const isLooksLike = !isGM && /{{\s*Looks\s?Like\s*=.*?}}/im.test(txt);
+ _.defaults(txtObj,defDefaults);
+ const showMore = /{{hide\d=/img.test(originalTxt);
+ const showLess = /{{desc\d=/img.test(originalTxt);
+ const txtRowID = generateRowID();
+ if (isShowMore && (showMore || showLess)) showMoreObj[txtRowID] = (preamble+' &{template:'+template+'}'+originalTxt.replace(/{{hide(\d)=/img,'{{reveal$1=').replace(/{{desc(\d)=/img,'{{hide$1=').replace(/{{reveal(\d)=/img,'{{desc$1=') );
+ const showMoreButton = (isShowMore && (showMore || showLess)) ? (' *show '+(showMore ? 'more' : 'less')+'...*') : '';
+ let content = outerFrame
+ +headerFrame
+ +header1+ (!isLooksLike ? txtObj.prefix : '')+' '+txtObj.title+' '+(!isLooksLike ? txtObj.name : '')+endHeader1
+ +(txtObj.subtitle && !isLooksLike ? (subtitle1+ txtObj.subtitle +endSubtitle1) : '')
+ +settings
+ +endHeaderFrame;
+ content += lastBodyFrame;
+ let j=1, crit=false, fumble=false, result=false;
+
+ _.each(txtObj,(t,k) => {
+ switch (k.dbName()) {
+ case 'result': result = resultTest(t); break;
+ case 'critroll': crit = state.attackMaster.weapRules.criticals && resultTest(t); break;
+ case 'fumbleroll': fumble = state.attackMaster.weapRules.criticals && resultTest(t); break;
+ default: break;
+ }
+ });
+
+ result = !fumble && (crit || result);
+// log('RPGMdefault: result = '+result+', crit = '+crit+', fumble = '+fumble);
+ _.each(txtObj,(t,k) => {
+ t = t.replace(/\/img,tableStyle);
+ t = t.replace(/\<\/table\>/img,endTableStyle);
+ txtObj[k] = t;
+ if (!t || !t.length) return;
+ let key = k.toLowerCase().replace(/\s/g,'');
+ if (key === 'lookslike') {
+ if (!isGM) {
+ content += (row2col[(j++)%2]+row2+ t +endRow2+endRow2col);
+ } else {
+// content += (row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col);
+ content += (row2col[(j++)%2]+row2+ '**'+k+'**: '+t +endRow2+endRow2col);
+ }
+ } else if (isLooksLike) {
+ return;
+ } else if (key === 'result' || key === 'crit_roll' || key === 'fumble_roll') {
+ switch (key) {
+ case 'result':
+ if (result) {txtObj.success = (txtObj.Success || txtObj.success).replace(/value1/ig,value1).replace(/value2/ig,value2).replace(/\[\[\d*?\[(.+?)\]\s?\]\]/g,rollVal);}
+ else {txtObj.failure = (txtObj.Failure || txtObj.failure).replace(/value1/ig,value1).replace(/value2/ig,value2).replace(/\[\[\d*?\[(.+?)\]\s?\]\]/g,rollVal);}
+ let resultTxt = (result ? !!txtObj.success.length : !!txtObj.failure.length) ? ' ' : '';
+ content += rowResult[result ? 0 : 1]+row1C+''+ (result ? 'Success' : 'Failure') +''
+ + resultTxt+(result ? txtObj.success : txtObj.failure)+(resultTxt.length?'':'')+endRow1C+endRowResult;
+ if (txtObj.successcmd && txtObj.successcmd.length && result && !crit) {
+ LibFunctions.sendAPI(LibFunctions.parseStr(txtObj.successcmd));
+ } else if (txtObj.failcmd && txtObj.failcmd.length && !result && !fumble) {
+ LibFunctions.sendAPI(LibFunctions.parseStr(txtObj.failcmd));
+ };
+ break;
+ case 'crit_roll':
+ content += (!crit ? '' : (rowResult[0]+row1C+ (txtObj.crit || 'Critical Success!') +endRow1C+endRowResult));
+ if (txtObj.critcmd && txtObj.critcmd.length && crit) LibFunctions.sendAPI(LibFunctions.parseStr(txtObj.critcmd));
+ break;
+ case 'fumble_roll':
+ content += (!fumble ? '' : (rowResult[1]+row1C+ (txtObj.fumble || 'Critical Failure!') +endRow1C+endRowResult));
+ if (txtObj.fumblecmd && txtObj.fumblecmd.length && fumble) LibFunctions.sendAPI(LibFunctions.parseStr(txtObj.fumblecmd));
+ break;
+ }
+ } else if (key === 'use') {
+ content += (row2col[(j++)%2]+row2+ '**'+k+'**: '+t +endRow2+endRow2col);
+ } else if (key.startsWith('hide')) {
+ return;
+ } else if (key.startsWith('section')) {
+ content += row1col[(j++)%2]+row1C+ t +endRow1C+endRow1col;
+ } else if (key === 'gminfo') {
+// if (isGM) content += (row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col);
+ if (isGM) content += (row2col[(j++)%2]+row2+ '**'+k+'**: '+t +endRow2+endRow2col);
+ } else if (!['prefix','name','title','subtitle','successcmd','failcmd','success','failure','crit','fumble','critcmd','fumblecmd','gmdesc'].includes(key) && !key.startsWith('desc')) {
+ content += row1col[(j++)%2]+rowHeader+ k +endRowHeader+rowBodyC+ t +endRowBodyC+endRow1col;
+ }
+ });
+ content += (isLooksLike ? '' : addDescs(txtObj,j,showMoreButton))
+ + 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, preamble );
+ break;
+ case 'rpgmmessage':
+ content = RPGMmessage( txt );
+ break;
+ case 'rpgmwarning':
+ case 'rpgmmenu':
+ content = RPGMdefault( txt, preamble, false );
+ break;
+ case 'rpgmweapon':
+ case 'rpgmammo':
+ case 'rpgmarmour':
+ case 'rpgmitem':
+ case 'rpgmring':
+ case 'rpgmwand':
+ case 'rpgmclass':
+ case 'rpgmdefault':
+ content = RPGMdefault( txt, preamble, true );
+ break;
+ default:
+ content = (template ? '&{template:'+template+'}' : '' ) + txt;
+ break;
+ }
+ while (/
/.test(content)) {content = content.replace(/
/mg,' ')};
+ content = (content[0] === '!' ? '' : preamble) + content;
+ setTimeout(() => sendChat(as?as:defaultAs,content,null,{noarchive:!archive, use3d:use3Ddice}), 0);
+ 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=LibFunctions.checkPlayersLive( charCS );
+ controlledBy = (!charCS ? '' : charCS.get('controlledby'));
+ if (controlledBy.includes('all')) {
+ to = '';
+ } else if (playerIsGM(senderId) || !charCS || !isPlayer) {
+ to = embedded ? '/w gm ' : '/w gm ';
+ } else if (makePublic) {
+ to = '';
+ } else {
+ to = (embedded ? ('/w "'+charCS.get('name')+'" ') : ('/w "' + charCS.get('name') + '" '));
+ }
+ return to;
+ }
+
+ /*
+ * A more reliable form of function to 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.sendMsgToWho = function(charCS,senderId,msg,div='',makePublic=false,embedded=false) {
+
+ var to, controlledBy, players, viewerID, isPlayer=false;
+// match = !embedded ? /(?<=^|}}\s*)^(?!\!|\/)/mg : /(? 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') + '" '));
+ }
+ if (!embedded) msg = msg.replace(/^&{template:/img,(to+div+'$&'))
+ .replace(/^(?!\!|\/)/,('$&'+to+div))
+ .replace(/^\!.*^(?!\!|\/)/mg,('$&'+to+div))
+ .replace(/^\/(?:w|em|ooc|talktomyself|fx|desc|as|emas)\s.*?^(?!\!|\/)/img,('$&'+to+div));
+
+ return embedded ? to : msg;
+ }
+
+ /**
+ * 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,senderId) {
+ if (!msg)
+ {return undefined;}
+ var who;
+
+ if (charCS) {
+ who = 'character|'+charCS.id;
+ } else {
+ who = '';
+ }
+ clearWaitTimer();
+ setTimeout(() => sendChat(who,msg,null,{use3d:use3Ddice}), 0);
+ };
+
+ /**
+ * Send API command to chat
+ */
+ LibFunctions.sendAPI = function(msg, senderId, from='', noSplit=false) {
+ var as;
+ if (!msg) {
+ log('sendMagicAPI: no msg');
+ return undefined;
+ }
+ if (!senderId || senderId.length == 0) {
+ as = '';
+ } else {
+ as = 'player|' + senderId;
+ }
+ let msgArray = noSplit ? [msg] : msg.split(/(?:
|\n)/);
+ _.each(msgArray, m => sendChat(as,m, null,{noarchive:!archive, use3d:use3Ddice}));
+ };
+
+ /**
+ * Send locally parsed feedback to the GM only!
+ */
+ LibFunctions.sendFeedback = function(msg,as,img) {
+ if (!msg)
+ {return;}
+ var gm = findTheGM(),
+ div = ''
+ + ' '
+ + ' ';
+ clearWaitTimer(gm);
+ setTimeout(() => sendChat(('player|'+gm),LibFunctions.sendMsgToWho(null,null,msg,div),null,{noarchive:!archive,use3d:false}), 100); //,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 div = ''
+ + ' '
+ + ' ';
+ clearWaitTimer(senderId);
+ setTimeout(() => sendChat((senderId ? 'player|'+senderId : charCS.get('name')),LibFunctions.sendMsgToWho(charCS,senderId,msg,div),null,{noarchive:!archive, use3d:use3Ddice}), 100);
+ }
+ };
+
+ /*
+ * Send a message to the player (rather than the character)
+ */
+
+ LibFunctions.sendResponseError = function(pid,msg,as,img) {
+ msg = '&{template:'+fields.warningTemplate+'}{{title=Warning!}}{{desc='+msg+'}}';
+ LibFunctions.sendResponsePlayer(pid,msg,as,img);
+ return;
+ }
+
+ /*
+ * Send an error message to the identified player.
+ * If that player is not online, send to the GM
+ */
+
+ LibFunctions.sendResponsePlayer = 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
+ + ''
+ + ' '
+ + ' '+msg;
+ clearWaitTimer(pid);
+ setTimeout(() => sendChat((as?as:defaultAs),content,null,{noarchive:false, use3d:use3Ddice}), 100);
+ };
+
+ /*
+ * 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 a simple error
+ */
+
+ LibFunctions.sendError = function(msg, cmd) {
+ var postErrorMsg = function( msg, cmd ) {
+ var content = '/w GM '
+ + ''
+ + ' '
+ + ' '
+ + errorMsgDiv + 'Error: ' + msg
+ + (cmd ? (' while processing command
' + cmd.content + ' ') : '')
+ + '';
+
+ sendChat(((cmd && cmd.who) ? cmd.who : defaultAs),content,null,{noarchive:false, use3d:false});
+ log('RPGMaster error: '+msg+ (cmd ? (' while processing command '+cmd.content) : ''));
+ };
+ setTimeout(postErrorMsg,500,msg,cmd);
+ };
+
+ /**
+ * Send an error caught by try/catch
+ */
+
+ LibFunctions.sendCatchError = function(apiName,msg,e,cmdStr='') {
+ var postCatchMsg = function(apiName,msg,e,cmdStr) {
+ if (!msg || !msg.content) {msg= {};msg.content = ''};
+ if (!cmdStr) cmdStr = msg.content;
+ log(apiName + ' error: ' + e.name + ', ' + e.message + ' when processing command ' + cmdStr);
+ let who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');
+ sendChat(apiName,`/w gm `+
+ ``+
+ ` There was an error while trying to run ${who}'s command: `+
+ ` ${cmdStr}
`+
+ ` Please send me this information so I can make sure this doesn't happen again (triple click for easy select in most browsers.): `+
+ ` `+
+ JSON.stringify({msg:msg, version:version, stack: e.stack, API_Meta})+
+ ` `+
+ ` `
+ )
+ };
+ setTimeout(postCatchMsg,500,apiName,msg,e,cmdStr);
+ };
+
+ /**
+ * 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,'|');
+ rollQuery = LibFunctions.parseStr(rollQuery);
+ command = command.replace(/gm{.+?}/i,rollQuery);
+ };
+ LibFunctions.sendFeedback( '&{template:'+fields.warningTemplate+'}{{title=DM Selection}}{{desc=As DM, you need to make [selections](!'+api+' '+senderId+' --'+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.}}');
+ LibFunctions.sendResponsePlayer( senderId, '&{template:'+fields.messageTemplate+'}{{title=DM Selection}}{{desc=Please wait while the DM makes a choice or dice roll.}}' );
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ /*
+ * Send a formatted "please wait" message to the specified player.
+ */
+
+ LibFunctions.sendWait = function(senderId,timer=500,source='') {
+ if (timer === 0) {
+ clearWaitTimer(senderId);
+ return;
+ } else if (waitList[senderId]) {
+ clearWaitTimer(senderId);
+ }
+ if (playerIsGM(senderId)) {
+ waitList[senderId] = setTimeout(() => {sendChat(defaultAs,('/w GM ' + waitMsgDiv + 'Gathering data - please wait'),null,{noarchive:!archive});
+ clearWaitTimer(senderId);
+ }, timer);
+ } else {
+ var player = getObj('player',senderId),
+ to = '/w "' + (!player ? 'GM' : player.get('_displayname')) + '" ';
+ waitList[senderId] = setTimeout(() => {sendChat('player|'+senderId,(to + waitMsgDiv + 'Gathering data - please wait'),null,{noarchive:!archive, use3d:false});
+ clearWaitTimer(senderId);
+ }, timer);
+ }
+ };
+
+
+ /* ------------------------------- 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, typeFilter='' ) {
+
+ var dbCS = findObjs({ type: 'character', name: dbName })[0] || undefined,
+ objDef,
+ objHeader = '',
+ foundItems = [],
+ dbHandout,csDBlist,
+ reDBdata = {speed:reSpellSpecs.speed,cost:reSpellSpecs.cost,recharge:reSpellSpecs.recharge};
+
+ var encodeStr = (str,encoders=dbEncoders) => encoders.reduce((m, rep) => m.replace(rep[0], rep[1]), str);
+
+ if (!dbCS) {
+ LibFunctions.sendError(('Database '+dbName+' not found'),null);
+ 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 objData = LibFunctions.resolveData(itemName,dbName,reNotAttackData,null,reDBdata).parsed,
+ objBody = encodeStr(item.get('action')),
+ objCT = objData.speed || 0,
+ objChg = objData.type || 'uncharged',
+ objCost = objData.cost || 0,
+ 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];
+ }
+ objType = _.uniq(objType.toLowerCase().split('|')).join('|');
+ if (typeFilter && typeFilter.length && !objType.includes(typeFilter)) return;
+
+ 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 if (_.isUndefined(listType)) {
+ 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,
+ db, shortName, attrName, objList,
+ rootList = ['mu_spells_db','pr_spells_db','powers_db','mi_db','race_db','class_db','attacks_db','styles_db','locks_traps_db'],
+ index = {};
+
+ _.each( dbNames, (dbFields, db) => {
+ if (state.MagicMaster.spellRules.denyCustom && db.toLowerCase().includes('custom')) return;
+ _.each( dbFields.db, (item, i) => {
+ rootDB = db.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),db,i];
+ });
+ });
+
+ objList = filterObjs( function(obj) {
+ if (obj.get('type') != 'ability') return false;
+ if (!(magicDB = getObj('character',obj.get('characterid')))) {
+ return false;
+ }
+ db = magicDB.get('name').toLowerCase().replace(/-/g,'_');
+ if (/\s*v\d*\.\d*/.test(db)) {
+ return false;
+ }
+ let validDB = false;
+ for (const rDB of rootList) {
+ if (db.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(db)) {
+ 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;
+ }
+ db = magicDB.get('name').toLowerCase().replace(/-/g,'_');
+ if (/\s*v\d*\.\d*/.test(db)) {return false;}
+ let validDB = false;
+ for (const rDB of rootList) {
+ if (db.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(db) || (!!!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( waitMsgDiv+'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 db = 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 (db && db.length && (db !== '-db' && !objCSname.startsWith(db))) 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);
+ };
+ };
+ };
+ };
+ };
+ };
+ 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 '+db,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(((!db || !db.length || db === '-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:(_.isUndefined(senderId) ? '' : 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 ---------------------------- */
+
+ /**
+ * Calculate/roll an attribute value that has a range
+ * Always tries to create a 3 dice bell curve for the value
+ **/
+
+ LibFunctions.calcAttr = function( attr='3:18' ) {
+ let attrRange = attr.split(':'),
+ low = parseInt(attrRange[0]),
+ high = parseInt(attrRange[1]);
+ if (high && !isNaN(low) && !isNaN(high)) {
+ let range = high - (low - 1);
+ if (range === 2) {
+ return low - 1 + randomInteger(2);
+ } else if (range === 3) {
+ return low - 2 + randomInteger(2) + randomInteger(2);
+ } else if (range === 5) {
+ return low - 2 + randomInteger(3) + randomInteger(3);
+ } else if ((range-2)%3 === 0) {
+ return low - 3 + randomInteger(Math.ceil(range/3)+1) + randomInteger(Math.floor(range/3)+1) + randomInteger(Math.floor(range/3)+1);
+ } else if ((range-1)%3 === 0) {
+ return low - 3 + randomInteger(Math.ceil(range/3)) + randomInteger(Math.ceil(range/3)) + randomInteger(Math.ceil(range/3));
+ } else if ((range)%3 === 0) {
+ return low - 3 + randomInteger((range/3)+1) + randomInteger((range/3)+1) + randomInteger(range/3);
+ }
+ }
+ return attr;
+ }
+
+ /**
+ * A function to calculate an internal dice roll
+ */
+
+ LibFunctions.rollDice = function( count, dice, reroll ) {
+ count = parseInt(count || 1);
+ dice = parseInt(dice || 8);
+ reroll = parseInt(reroll || 0);
+ let total = 0,
+ roll;
+ for (let d=0; d id !== '' && id !== GMid);
+ if (!playerIds || !playerIds.length) return GMid;
+ if (playerIds[0] !== 'all') {
+ let pid = playerIds.find( p => (getObj('player',p) && !!getObj('player',p).get('_online')));
+ if (pid) return pid;
+ }
+ playerObjs = filterObjs(p => (p.get('_type') === 'player' && !!p.get('_online') && p.id !== GMid));
+ }
+ }
+ return (!playerObjs || !playerObjs.length) ? GMid : playerObjs[0].id;
+ };
+
+ /**
+ * Find a Character object given a name only,
+ * returning the first match or undefined
+ */
+
+ LibFunctions.findCharacter = function( name ) {
+ var charObj = findObjs({ _type: 'character' , name: name },{caseInsensitive: true});
+ return ((charObj && charObj.length) ? charObj[0] : undefined);
+ }
+
+ /**
+ * Function to find the ID of a live player
+ * that controls the specified character
+ */
+
+ LibFunctions.checkPlayersLive = function( charCS ) {
+ let playerID, controlledBy = (!charCS ? '' : charCS.get('controlledby'));
+ if (controlledBy.length > 0) {
+ controlledBy = controlledBy.split(',');
+ let viewerID = (state.roundMaster && state.roundMaster.viewer && state.roundMaster.viewer.is_set) ? (state.roundMaster.viewer.pid || null) : null;
+ let players = controlledBy.filter(id => id != viewerID);
+ if (players.length) {
+ playerID = _.find( controlledBy, function(playerID) {
+ players = findObjs({_type: 'player', _id: playerID, _online: true});
+ return (players && players.length > 0);
+ });
+ };
+ };
+ return playerID;
+ };
+
+ /**
+ * A function to return the specified player ID, or
+ * the first live player who controls the character,
+ * or the first live player who controls the token
+ * representing a character, or senderId, or the GM.
+ */
+
+ LibFunctions.fixSenderId = function( args, selected, senderId ) {
+
+ let playerID = args[0] || (selected && selected.length ? selected[0]._id : senderId),
+ playerObj = getObj('player',playerID);
+ if (!playerObj) playerID = LibFunctions.checkPlayersLive( getObj('character',args[0]) );
+ if (!playerID) playerID = LibFunctions.checkPlayersLive( LibFunctions.getCharacter(args[0]) );
+
+ return playerID || senderId;
+ };
+
+ /*
+ * Parse a data string for attribute settings
+ */
+
+ LibFunctions.parseData = function( attributes, reSpecs, def=true, charCS, item='', row='' ) {
+
+ var parsedData = {},
+ val,
+ varRes = ( m, w, v = 'current' ) => LibFunctions.parseStr((LibFunctions.attrLookup( charCS, [fields.ItemVar[0]+item+'+'+row+'-'+w,'current'] ) || '').split('/')[v] || '');
+
+ if (charCS) while (reVars.test(attributes)) attributes = attributes.replace(reVars,varRes);
+ _.each( reSpecs, spec => {
+ if (_.isUndefined(spec) || _.isUndefined(spec.re)) return;
+ val = attributes.match(spec.re);
+ if (!!val && val.length>1 && val[1].length) {
+ parsedData[spec.field] = (val.length == 3 && val[2]) ? [val[1],val[2]] : 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, charCS, reParseTable, row='', quals=[], defBase=true, doneList=[], topItem, debugging=false ) {
+
+ try {
+
+ if (_.isEmpty(reParseTable)) reParseTable = undefined;
+
+ var thisObj, thisSpecs, baseObj, thisData, thisAttr, parsedData,
+ rDB = dBase.toLowerCase().replace(/-/g,'_'),
+ isSpell = rDB.includes('spells_db'),
+ isMI = rDB.startsWith('mi_db'),
+ isRC = !isSpell && !isMI,
+ parseTable = reClassSpecs,
+ baseData = [['']],
+ baseParsed = LibFunctions.parseData( '', (reParseTable || (!isRC ? reSpellSpecs : reClassSpecs)), defBase ),
+ baseAttr = LibFunctions.parseData( '', reAttr, defBase ),
+ debugging = debugging || false, // name.dbName().includes('berserking'),
+ varRes = ( m, w, v = 0 ) => LibFunctions.parseStr((LibFunctions.attrLookup( charCS, [fields.ItemVar[0]+(topItem || name)+'+'+row+'-'+w,'current'] ) || '').split('/')[v] || '');
+
+ if (!name || !name.trim().length || doneList.includes(name.dbName())) throw new Error('resolveData: no name or already processed '+name);
+ thisObj = LibFunctions.abilityLookup( dBase, name, charCS, true );
+ if (!thisObj.obj) throw new Error('resolveData: no definition of '+name+' in '+dBase);
+ doneList.push(name.dbName());
+ thisSpecs = thisObj.specs();
+ if (!thisSpecs || !thisSpecs[0]) throw new Error('resolveData: no Specs in definition of '+name);
+ if (debugging) log('resolveData: weapon '+name+' thisSpecs = '+thisSpecs[0]+', item body = '+thisObj.obj[1].body);
+ baseObj = LibFunctions.resolveData( ((isMI ? thisSpecs[0][5] : thisSpecs[0][4]) || ''), dBase, reThisData, charCS, reParseTable, row, quals, defBase, doneList, (topItem || name), debugging );
+ baseParsed = baseObj.parsed; baseAttr = baseObj.attrs; baseData = baseObj.raw;
+ thisData = thisObj.data(reThisData);
+ if (!thisData || !thisData[0]) thisData = [['']];
+ _.each( quals, (q,k) => thisData[0][0] = thisData[0][0].replace(new RegExp('\\?\\?'+k,'g'),q));
+ if (debugging) log('resolveData: weapon '+name+' quals = '+quals+', after ??# replacement, thisData.length = '+thisData.length+', thisData = '+thisData);
+ thisData[0][0] = thisData[0][0].replace(/\?\?\d/g,'0');
+ if (isMI || isSpell) {
+ if (debugging && !miTypeLists[thisSpecs[0][2].dbName().split('|')[0]]) log('resolveData: unable to find '+thisSpecs[0][2].dbName().split('|')[0]);
+ switch ((miTypeLists[thisSpecs[0][2].dbName().split('|')[0]] || {type:''}).type) {
+ case 'weapon':
+ case 'ammo':
+ parseTable = reWeapSpecs;
+ break;
+ case 'armour':
+ case 'armor':
+ parseTable = reACSpecs;
+ break;
+ default:
+ parseTable = reSpellSpecs;
+ break;
+ };
+ };
+ while (reVars.test(thisData[0][0])) thisData[0][0] = thisData[0][0].replace(reVars,varRes);
+ parsedData = LibFunctions.parseData( thisData[0][0], (reParseTable || parseTable), false, charCS, name, row );
+ thisAttr = LibFunctions.parseData( (parsedData.cattr || '')+',', reAttr, false, charCS, name, row );
+ if (baseParsed) {
+ if (!parsedData.cattr) {
+ parsedData.cattr = baseParsed.cattr;
+ thisAttr = baseAttr;
+ } else if (baseAttr) {
+ thisAttr = _.mapObject(Object.assign(baseAttr,_.pick(thisAttr,a => !!a)), attr => attr !== '-' ? attr : '');
+ }
+ if (debugging) log('resolveData: baseParsed = '+_.pairs(baseParsed).flat()+', parsedData = '+_.pairs(parsedData).flat());
+ parsedData = _.mapObject(Object.assign(baseParsed,_.pick(parsedData,a => !!a)), attr => attr !== '-' ? attr : '');
+ let dataCount = reIsAttackData.test(thisData[0][0]) ? thisData.length : 1;
+ for (let i=0; i < dataCount; i++) {
+ while (reVars.test(thisData[i][0])) thisData[i][0] = thisData[i][0].replace(reVars,varRes);
+ if (!!baseData.length && i < thisSpecs.length) {
+ thisData[i][0] = '['+_.pairs(Object.assign(
+ _.object(baseData[0][0].replace(/^.*?=\[/,'').replace(/[\[\]]/g,'').split(',').map(v => {v = v.trim().split(':');v[0] = v[0].toLowerCase();return v})),
+ _.object(thisData[i][0].replace(/^.*?=\[/,'').replace(/[\[\]]/g,'').split(',').map(v => {v = v.trim().split(':');v[0] = v[0].toLowerCase();return v}))
+ )
+ ).map(v => v.join(':')).filter(v => v !== ':').join()+']';
+ if (baseData.length > 1) {baseData.shift();} // else {baseData = [['']]};
+ };
+ };
+ }
+ if (debugging)log('resolveData: merged data for '+name+' thisData = '+thisData);
+ if (parsedData.bag || (parsedData.numpowers && parsedData.numpowers[0]!=='=')) thisData = thisData.concat(baseData);
+ if (debugging)log('resolveData: result is '+thisData.length+' long = '+thisData);
+ return {parsed:parsedData, attrs:thisAttr, raw:((thisData[0].length === 1 && thisData[0][0].trim() === '[]') ? '' : thisData)};
+
+ } catch (err) {
+ if (err.message.startsWith('resolveData')) {
+ if (debugging) log(err.message);
+ return {parsed:baseParsed, attrs:baseAttr, raw:baseData};
+ } else {
+ LibFunctions.sendCatchError( 'RPGM Library',null,err,'RPGM Library resolveData()');
+ }
+ }
+ };
+
+ /*
+ * 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) {
+ if (!silent) LibFunctions.sendError('Invalid token_id in arguments');
+ return undefined;
+ };
+
+ charCS = getObj( 'character', tokenID );
+ if (charCS) return charCS;
+
+ curToken = getObj( 'graphic', tokenID );
+
+ if (!curToken) {
+ if (!silent) LibFunctions.sendError('Invalid token_id in arguments');
+ return undefined;
+ };
+
+ charID = curToken.get('represents');
+
+ if (!charID) {
+ if (!silent) LibFunctions.sendError(('The token "'+curToken.get('name')+'" does not represent a character sheet'));
+ return undefined;
+ };
+
+ charCS = getObj('character',charID);
+
+ if (!charCS) {
+ if (!silent) LibFunctions.sendError(('The token "'+curToken.get('name')+'" does not represent a character sheet'));
+ 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 = _.isUndefined(state.RPGMaster.tokenFields) ? -1 : 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);
+ attrVal = !isNaN(attrVal) ? parseFloat(attrVal) : undefined;
+ }
+ if (isNaN(attrVal) && !linkedToken && fieldIndex >= 0) {
+ attrVal = parseFloat(curToken.get('bar'+(fieldIndex+1)+'_'+token_property));
+ attrName = barName = 'bar'+(fieldIndex+1);
+ }
+ 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, senderId, parseTable ) {
+
+ try {
+ 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, true );
+ }
+ 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', dB:fields.RaceDB, base:'warrior', dBbase:fields.ClassDB, level:0, obj:LibFunctions.abilityLookup( fields.ClassDB, 'creature', charCS ).obj}];
+ classDef = classDef.map(c => {let d = LibFunctions.resolveData((c.name || charClass), (c.dB || dB), reData, null, parseTable); c.classData = d.parsed; c.attrData = d.attrs; c.rawData = d.raw; return c});
+
+ } catch (e) {
+ LibFunctions.sendCatchError( 'RPGM Library',(senderId ? msg_orig[senderId] : null),e,'RPGM Library classObjects()');
+ }
+ 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,
+ reItemSpecs = { weapons: reClassSpecs.weapons,
+ armour: reClassSpecs.armour,
+ majorsphere:reClassSpecs.majorsphere,
+ minorsphere:reClassSpecs.minorsphere,
+ bannedsphere:reClassSpecs.bannedsphere,
+ alignment: reClassSpecs.alignment,
+ race: reClassSpecs.race,
+ };
+
+ var classAllowed = LibFunctions.classObjects( charCS ).some( elem => {
+ if (wt.includes('innate') || 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);
+ }),
+ raceAllowed = true;
+
+ forceFalse = false;
+ let allowedItems = LibFunctions.resolveData( (LibFunctions.attrLookup( charCS, fields.Race ) || 'human'), fields.RaceDB, reClassRaceData, charCS, reItemSpecs, '', [], true, [] ).parsed[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 ) {
+
+ var itemData = LibFunctions.resolveData( dbItem.name, fields.MagicItemDB, reNumSpellsData ).raw,
+ itemSpells = itemData ? [...('['+itemData+']').matchAll(/\[.+?\]/g)] : [],
+ spellSet = {MU:[[],[]],PR:[[],[]],PW:[[],[]],AB:[[],[]]};
+
+ _.each(itemSpells, spell => {
+ let parsedData = LibFunctions.parseData( spell[0], reSpellSpecs );
+ if (parsedData && parsedData.spell && ['MU','PR','PW','AB'].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.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.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.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, senderId, 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) {
+
+ var list = [],
+ alphaList = [],
+ rDB = rootDB.toLowerCase().replace(/-/g,'_'),
+ typeList;
+
+ var addItemToList = function( objIndex, objName, mapObj, objType ) {
+ var error = false;
+ try {
+ var typeList;
+ if (objIndex[0].length) {
+ let obj = getObj('ability',objIndex[0]);
+ if (!obj) return true;
+ 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('|');
+ if (typeList.includes('format') || typeList.includes('hide')) continue;
+ 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))) {
+ let listName = obj.get('name').dispName();
+ let listQuery = !mapObj[t] ? '' : (!mapObj[t].query ? '' : '%%'+mapObj[t].query).replace(/%/g,'%%')
+ .replace(/\&/g,'&')
+ .replace(/\?/g,'?')
+ .replace(/{/g,'&#123;')
+ .replace(/}/g,'&#125;')
+ .replace(/\|/g,'&#124;')
+ .replace(/\,/g,'&#44;');
+ list.push(listName+(alphabet ? ',' : ',')+listName+listQuery);
+ break outer_block;
+ }
+ }
+ }
+ }
+ } else {
+ typeList = dbNames[objIndex[2]].db[objIndex[3]].type.dbName().split('|');
+ if (typeList.includes('format') || typeList.includes('hide')) return error;
+
+ 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))) {
+ let listName = dbNames[objIndex[2]].db[objIndex[3]].name.dispName();
+ let listQuery = !mapObj[t] ? '' : (!mapObj[t].query ? '' : '%%'+mapObj[t].query).replace(/%/g,'%%')
+ .replace(/\&/g,'&')
+ .replace(/\?/g,'?')
+ .replace(/{/g,'&#123;')
+ .replace(/}/g,'&#125;')
+ .replace(/\|/g,'&#124;')
+ .replace(/\,/g,'&#44;');
+ list.push(listName+(alphabet ? ',' : ',')+listName+listQuery);
+ break;
+ }
+ }
+ }
+ } catch (e) {
+ log('LibFunction getMagicList: JavaScript '+e.name+': '+e.message+' while processing object '+objName);
+ LibFunctions.sendCatchError('RPGMaster Library',(senderId ? msg_orig[senderId] : null),e);
+ error = true;
+
+ } finally {
+ return error;
+ }
+ };
+
+ if (_.isUndefined(DBindex[rDB])) {
+ for (const db of _.keys(DBindex)) {
+ if (rDB.startsWith(db)) {
+ rDB = db;
+ break;
+ }
+ }
+ }
+ _.each( DBindex[rDB], (objIndex,objName) => {
+ addItemToList( objIndex, objName, mapObj, objType );
+ });
+ if (!list.length || !list[0].length) {
+ list = defList.split('|');
+ }
+ list = _.uniq(list.filter( list => !!list ).sort(),true);
+
+ if (alphabet) {
+ 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.toUpperCase().charCodeAt(10)==i ),
+ list.filter( n => n.toUpperCase().startsWith('RING OF ') && n.toUpperCase().charCodeAt(8)==i ),
+ list.filter( n => n.toUpperCase().startsWith('SCROLL OF ') && n.toUpperCase().charCodeAt(10)==i ));
+ if (subList && subList.length) {
+ if (subList.length === 1) subList.push(subList[0]);
+ alphaList.push(String.fromCharCode(i)+',?{Choose from |'+(subList.join('|'))+'}');
+ }
+ };
+ list = alphaList;
+ }
+ if (other) {
+ 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, row, miAlt ) {
+ var specs = miObj.specs(),
+ mi, miType, miAlt, data;
+ 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';
+ if (!miAlt) miAlt = LibFunctions.resolveData(miObj.obj[1].name,fields.MagicItemDB,reNotAttackData,null,{itemType:reSpellSpecs.itemType},row,null,false).parsed.itemType;
+ specs = specs.find(itemSpecs => itemSpecs[2].toLowerCase().includes(mi.toLowerCase()));
+ switch (miType) {
+ case 'weapon':
+ case 'ammo':
+ mi = miAlt || ((specs || ['','','','','item'])[4]);
+ break;
+ case 'armour':
+ case 'armor':
+ mi = miAlt || ((specs || ['','mi'])[1]);
+ break;
+ case 'miscellaneous':
+ mi = miAlt || mi;
+ break;
+ default:
+ if (mi.toLowerCase() === 'magic') {
+ mi = miAlt || ((specs || ['','','','','item'])[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) {
+ var level = Math.max(((parseInt((LibFunctions.attrLookup( charCS, fields.Monster_hitDice ) || 0),10)
+ + ((parseInt((LibFunctions.attrLookup( charCS, fields.Monster_hpExtra ) || 0),10) >= 3) ? 1 : 0)) || 0),
+ ((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)) || 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;
+
+ casterType = casterType.toUpperCase();
+
+ 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.dbName();
+ 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, type ) {
+
+ if (!type) {
+ 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]
+ );
+ } else if (!isNaN(type)) {
+ return parseInt(type);
+ } else {
+ type = type.split('=');
+ let fromType = type[0].split('|'),
+ toType = (type[1].toUpperCase() || 'F')[0],
+ classNum = toType === 'O' ? 4
+ :(toType === 'W' ? 1
+ :(toType === 'P' ? 2
+ :(toType === 'R' ? 3
+ : 0 ))),
+ thac0 = 20,
+ field;
+
+ _.each( fromType, t => {
+ switch (t[0].toUpperCase()) {
+ default: field = fields.Fighter_level;break;
+ case 'W': field = fields.Wizard_level; break;
+ case 'P': field = fields.Priest_level; break;
+ case 'R': field = fields.Rogue_level; break;
+ case 'O': field = fields.Psion_level; break;
+ }
+ thac0 = Math.min( thac0, baseThac0table[classNum][LibFunctions.attrLookup( charCS, field ) || 0]);
+ });
+ return thac0;
+ }
+ }
+
+ /*
+ * Parse the Class Databases to update internal rule tables with
+ * any changes held for specific Class definitions
+ */
+
+ LibFunctions.parseClassDB = function(forceUpdate=false) {
+
+ var doParse = function( rootDB, saveMods ) {
+ let isClass = rootDB === fields.ClassDB,
+ indexDB = rootDB.toLowerCase().replace(/-/g,'_');
+ if (!DBindex[indexDB]) return;
+ for (const ClassName in DBindex[indexDB]) {
+ let def = LibFunctions.abilityLookup(rootDB, ClassName),
+ type = !def.obj ? '' : def.obj[1].type,
+ classSpecs = def.specs(reSpecs) || [['','','','','']],
+ isCreature = type.toLowerCase().includes('creature') || (classSpecs && classSpecs[0] && classSpecs[0][4] && String(classSpecs[0][4]).toLowerCase().includes('creature')),
+ dataObj = LibFunctions.resolveData( ClassName, rootDB, /}}\s*?(?:Class|Race)Data\s*?=(.*?){{/im, null, null, '', [], false );
+
+ if (isClass) {
+ let classType;
+ if (classSpecs && !_.isNull(classSpecs)) {
+ if (classSpecs.some( s => {
+ if (s && s.length >= 5) {
+ classType = (s[1]||'').dbName();
+ return (((s[4]||'').dbName() == 'wizard' ) && !ordMU.includes(classType) && (dataObj.parsed.specmu == 1));
+ }
+ return false;
+ })) {
+ if (!specMU.includes(classType)) specMU.push(classType);
+ } else {
+ if (!ordMU.includes(classType)) ordMU.push(classType);
+ };
+ };
+ }
+
+ if (dataObj.raw) {
+ for (let r=0; r {
+ pen = pen.toLowerCase().split('=');
+ pen[0] = pen[0].dbName();
+ pen[1] = parseInt(pen[1]) || 0;
+ return pen;
+ });
+ }
+ let rowArray = rowData.toLowerCase().replace(/\[/g,'').replace(/\]/g,'').split(','),
+ svlArray = rowArray.filter(elem => elem.startsWith('svl'));
+
+ if (svlArray && svlArray.length) {
+ svlArray.sort((a,b)=>{parseInt((a.match(/svl(\d+):/)||[0,0])[1])-parseInt((b.match(/svl(\d+):/)||[0,0])[1]);});
+ saveLevels[name] = [];
+ baseSaves[name] = [];
+ let oldLevel = 0,
+ baseIndex = 0;
+ svlArray.forEach(svl => {
+ let sv = svl.match(/svl(\d+):([\d\|]+)/),
+ level = parseInt(sv[1] || 0),
+ saves = (sv[2] || '20|20|20|20|20').split('|');
+ saveLevels[name].length = level+1;
+ saveLevels[name].fill(baseIndex,oldLevel,level+1);
+ if (baseIndex == 0 && level != 0) {
+ baseSaves[name].push([16,18,17,20,19]);
+ baseIndex++;
+ }
+ saves.length = 5;
+ baseSaves[name].push(saves);
+ baseIndex++
+ oldLevel = level+1;
+ });
+ };
+ svlArray = rowArray.filter(elem => {return /^\s*sv[a-z0-9]{3}:/.test(elem);});
+ if (svlArray && svlArray.length) {
+ saveMods[name] = {att:'con',par:0.0,poi:0.0,dea:0.0,rod:0.0,sta:0.0,wan:0.0,pet:0.0,pol:0.0,bre:0.0,spe:0.0,str:0.0,con:0.0,dex:0.0,int:0.0,wis:0.0,chr:0.0};
+ svlArray.forEach(svm => {
+ let sv = svm.match(/sv([a-z0-9]{3}):([+-]?\d+\.?\d*|\w{3})(L\d+)?/i);
+ if (sv[1] == 'all') {
+ saveMods[name] = _.mapObject(saveMods[name], (v,k) => {return k != 'att' ? v + (parseFloat(sv[2] || 0) || 0) : v;});
+ } else if (['sav','atr','chk'].includes(sv[1])) {
+ let saves = sv[1] === 'sav' ? saveFormat.Saves : (sv[1] === 'atr' ? saveFormat.Attributes : saveFormat.Checks);
+ _.each(saves, s => saveMods[name][s.tag] = saveMods[name][s.tag] + (parseFloat(sv[2] || 0) || 0));
+ } else {
+ let plv = parseInt(sv[3]) || 1;
+ saveMods[name][sv[1]] = (sv[1] != 'att') ? (String(parseFloat(sv[2] || 0) || 0)+(sv[3] || '')) : (sv[2] || 'con').dbName();
+ }
+ });
+ };
+ svlArray = rowArray.filter(elem => {return /^\s*sv[a-z0-9]{3}\+:/.test(elem);});
+ if (svlArray && svlArray.length) {
+ classSaveMods[name] = {att:'con',par:0.0,poi:0.0,dea:0.0,rod:0.0,sta:0.0,wan:0.0,pet:0.0,pol:0.0,bre:0.0,spe:0.0,str:0.0,con:0.0,dex:0.0,int:0.0,wis:0.0,chr:0.0};
+ svlArray.forEach(svm => {
+ let sv = svm.match(/sv([a-z0-9]{3})\+:([+-]?\d+\.?\d*|\w{3})/);
+ if (sv[1] == 'all') {
+ classSaveMods[name] = _.mapObject(classSaveMods[name], (v,k) => {return k != 'att' ? v + (parseFloat(sv[2] || 0) || 0) : v;});
+ } else if (['sav','atr','chk'].includes(sv[1])) {
+ let saves = sv[1] === 'sav' ? saveFormat.Saves : (sv[1] === 'atr' ? saveFormat.Attributes : saveFormat.Checks);
+ _.each(saves, s => classSaveMods[name][s.tag] = classSaveMods[name][s.tag] + (parseFloat(sv[2] || 0) || 0));
+ } else {
+ classSaveMods[name][sv[1]] = (sv[1] != 'att') ? (parseFloat(sv[2] || 0) || 0) : (sv[2] || 'con').dbName();
+ }
+ });
+ };
+ };
+ };
+ if (isCreature) {
+ if (!clTypeLists[classSpecs[0][2].toLowerCase()]) clTypeLists[classSpecs[0][2].toLowerCase()] = {type:'creature',field:fields.RaceCreatureList,query:''};
+ if (dataObj.parsed.query && dataObj.parsed.query.length) {
+ let query = LibFunctions.parseStr(dataObj.parsed.query).split('|');
+ let question = query.shift();
+ clTypeLists[classSpecs[0][2].toLowerCase()].query = '?{'+question + '|'
+ + query.map( q => {
+ let sq = q.split('%');
+ return sq[0]+','+sq.join('%%');
+ }).join('|')
+ + '}';
+ };
+ };
+ };
+ return;
+ };
+ if (classesParsed && !forceUpdate) return;
+ doParse( fields.ClassDB, classSaveMods );
+ doParse( fields.RaceDB, raceSaveMods );
+ classesParsed = true;
+ LibFunctions.sendFeedback( waitMsgDiv+'RPGMaster is now ready.' );
+
+ return;
+ };
+
+ /*
+ * 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,rules:[]},
+ types = {par:'sav',poi:'sav',dea:'sav',rod:'sav',sta:'sav',wan:'sav',pet:'sav',pol:'sav',bre:'sav',spe:'sav',str:'atr',con:'atr',dex:'atr',int:'atr',wis:'atr',chr:'atr'},
+ reSave = /[,\[\s]sv([a-z0-9]{3}):([-\+\*\/\=\^vfc\d\.;\(\)]+)[,\s\]]/g,
+ reRules = /[,\[\s]rules:(.*?)[,\s\]]/i;
+
+ var tokenID,
+ charCS,
+ attkMenu,
+ msg = '',
+ massMod = false;
+
+ var checkThisSave = function(attkMenu,curToken,senderId,silent,selected) { // length
+
+ return new Promise(resolve => {
+ try {
+ tokenID = attkMenu ? curToken.id : curToken._id;
+ charCS = LibFunctions.getCharacter( tokenID, true );
+
+ var scanForSaves = function( item, trueItem, classArray, specsArray, dataArray, itemMods, setFlags ) {
+ let modsClass = classArray[0];
+ _.each( dataArray, data => {
+ if (!data) return;
+ if (!itemMods[modsClass] || _.size(itemMods[modsClass]) < _.size(blankMods)) itemMods[modsClass] = _.clone(blankMods);
+ let svRules = (data[0].match(reRules) || ['',''])[1].toLowerCase().replace(/[_\s]/g,'').split('|').map(r => r.replace(/\-/g,(match,i,s)=>(i>0?'':match))),
+ inHand = !svRules.includes('+inhand') || !_.isUndefined(LibFunctions.getTableField( charCS, {}, fields.InHand_table, fields.InHand_trueName ).tableFind( fields.InHand_trueName, trueItem )),
+ worn = !svRules.includes('+worn') || LibFunctions.classAllowedItem( charCS, trueItem, specsArray[0][1].dbName(), specsArray[0][4].dbName(), 'ac' ),
+ conflict = '',
+ testRules = [],
+ adds = !(_.some(itemMods,(mi,c) => {conflict=c;return (svRules.includes( '-'+c ) || _.some(classArray,mic => {return mi.rules.includes('-'+mic);}))}));
+ if (_.isUndefined(addedText[modsClass]) && (!inHand || !worn || !adds)) addedText[modsClass] = '';
+ if (!inHand && !silent) addedText[modsClass] += '{{'+item+'=Is not currently in hand}}';
+ if (!worn && !silent) addedText[modsClass] += '{{'+item+'=Is not of a usable type}}';
+ if (!adds && !silent) addedText[modsClass] += '{{'+item+'=Does not combine with items of class '+conflict+'}}';
+ if (!inHand || !worn || !adds) return;
+ let saveMods = [...data[0].matchAll(reSave)];
+ _.each( saveMods, m => {
+ let n = LibFunctions.evalAttr('-+='.includes(m[2][0]) ? m[2].substring(1) : m[2]);
+ m[2] = ('-+='.includes(m[2][0]) ? m[2][0] : '') + String(n);
+ let saveSpec;
+ if (_.isUndefined(addedText[modsClass])) addedText[modsClass] = '';
+ if (!silent) addedText[modsClass] += '{{'+item+'=';
+ let every = m[1] === 'all',
+ attr = m[1] === 'atr',
+ save = m[1] === 'sav';
+ if (save || every || attr) {
+ massMod = true;
+ let msg = 'All '+(every ? '' : (attr ? 'attribute ' : 'save '))+'mods: '+m[2];
+ if (!silent) addedText[modsClass] += msg;
+ let tempObj = itemMods[modsClass];
+ itemMods[modsClass] = _.mapObject(tempObj, function(v,k) {
+ if (k != 'att' && k != 'rules' && !_.isUndefined(blankMods[k])) {
+ if (every || types[k] == m[1]) {
+ if ('+-'.includes(m[2][0]) && !setFlags[k]) {
+ return (v+(parseInt(m[2]) || 0));
+ } else if (m[2][0] == '=') {
+ let newVal = parseInt(m[2].substring(1)) || 0;
+ if (setFlags[k]) {
+ if (!silent && v < newVal) addedText[modsClass] = '{{'+item+'='+msg;
+ return Math.max(v,newVal);
+ } else {
+ setFlags[k] = true;
+ if (!silent) addedText[modsClass] = '{{'+item+'='+msg;
+ return newVal;
+ }
+ } else if (!setFlags[k]) {
+ if (!silent && v < (parseInt(m[2]) || 0)) addedText[modsClass] = '{{'+item+'='+msg;
+ return Math.max(v,(parseInt(m[2]) || 0));
+ } else {
+ return v;
+ }
+ } else {
+ return v;
+ }
+ } else {
+ return v;
+ }
+ log('handleCheckSaves: checked everything, should not get here');
+ return v;
+ });
+ } else {
+ if (_.isUndefined(mods[m[1]])) mods[m[1]] = 0;
+ if (_.isUndefined(itemMods[modsClass][m[1]])) itemMods[modsClass][m[1]] = 0;
+ if (_.isUndefined(setFlags[m[1]])) setFlags[m[1]] = false;
+ let v = itemMods[modsClass][m[1]] || 0;
+ if (m[1] != 'att') {
+ if (!silent) addedText[modsClass] += (xlateSave[m[1]] || trueItem)+': '+m[2]+', ';
+ if ('+-'.includes(m[2][0]) && !setFlags[m[1]]) {
+ itemMods[modsClass][m[1]] += (parseInt(m[2]) || 0);
+ } else if (m[2][0] === '=') {
+ let newVal = parseInt(m[2].substring(1)) || 0;
+ if (setFlags[m[1]]) {
+ itemMods[modsClass][m[1]] = Math.max(v,newVal);
+ } else {
+ setFlags[m[1]] = true;
+ itemMods[modsClass][m[1]] = newVal;
+ }
+ } else if (!setFlags[m[1]]) {
+ itemMods[modsClass][m[1]] = Math.max(v,(parseInt(m[2]) || 0));
+ }
+ } else {
+ itemMods[modsClass].att = v;
+ }
+ };
+ if (!silent) addedText[modsClass] += '}}';
+ });
+ itemMods[modsClass].rules = itemMods[modsClass].rules ? itemMods[modsClass].rules.concat(svRules) : svRules;
+ });
+ return [itemMods,setFlags];
+ };
+
+
+ if (!charCS) {
+ return;
+ }
+ var 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,
+ SaveMods = LibFunctions.getTable( charCS, fieldGroups.SAVES ),
+ 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)) || _.create(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 = {},
+ modName,
+ attribute, attrVal, item,
+ addedText = {},
+ itemText = '',
+ content = silent ? '' : '&{template:'+fields.defaultTemplate+'}';
+
+ content += silent ? '' : '{{name='+tokenName+'\'s Saving Throws}}';
+
+ classes.forEach( c => {
+ if (!saveLevels[c.name]) {
+ classSaves = baseSaves[c.base][saveLevels[c.base][Math.min(c.level,saveLevels[c.base].length-1)]];
+ } else {
+ classSaves = baseSaves[c.name][saveLevels[c.name][Math.min(c.level,saveLevels[c.name].length-1)]];
+ }
+ if (!saves || !saves.length) {
+ saves = classSaves;
+ } else {
+ saves = saves.map((v,k)=> Math.min(v,classSaves[k]));
+ }
+ if (!silent) itemText += '{{'+c.obj[1].name+'=Level '+c.level+'='+classSaves+'}}';
+ });
+
+ switch (mods.att.toLowerCase()) {
+ 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 (!silent && _.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 (!silent && v != 0) itemText += xlateSave[k]+':'+(Math.floor(attrVal != -1 ? (attrVal/v) : v)+raceBonus[k])+', ';
+ return Math.floor(v != 0 ? (attrVal != -1 ? (attrVal/v) : v) : 0)+raceBonus[k];
+ }
+ });
+ if (!silent && _.some(mods,(m,k)=>!!m && k!='att')) itemText += '}}';
+
+ let dexBonus = 0-(parseInt(LibFunctions.attrLookup( charCS, fields.Dex_acBonus )) || 0);
+ if (dexBonus) {
+ mods.dex += dexBonus;
+ itemText += '{{Dexterity of '+LibFunctions.attrLookup( charCS, fields.Dexterity )+'='+(dexBonus > 0 ? 'Bonus' : 'Penalty')+' of '+dexBonus+'}}';
+ }
+
+ classes.forEach( c => {
+ classMods = classSaveMods[c.name] || classSaveMods[c.base] || classSaveMods.undefined;
+ classMods = _.mapObject(classMods,v=>{
+ let plv = (v || '').match(/([-\+]?\d+)L(\d+)/i);
+ if (plv && plv[2] != 0) v = plv[1] * Math.ceil(c.level/plv[2]);
+ return parseInt(v);
+ });
+ 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 (!silent && _.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 += xlateSave[k]+':'+v+' ') : ''));
+ }
+ itemText += '}}';
+ }
+ });
+
+ for (let itemRow = ItemNames.table[1]; !_.isUndefined(item = ItemNames.tableLookup( fields.Items_name, itemRow, false )); itemRow++) {
+ if (item && item.length && item != '-') {
+ let trueItem = ItemNames.tableLookup( fields.Items_trueName, itemRow );
+ let itemObj = LibFunctions.abilityLookup( fields.MagicItemDB, trueItem, charCS );
+ if (itemObj.obj) {
+ let specsArray = itemObj.specs(/}}\s*specs=\s*?(.*?)\s*?{{/im),
+ miClass = specsArray ? (specsArray[0][2].dbName() || 'magicitem') : 'magicitem';
+
+ 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)) {
+ if (!silent) itemText += '{{'+item+'=Is not currently worn}}';
+ continue;
+ }
+ }
+ [miMods,setFlags] = scanForSaves( item, trueItem, miClass.dbName().split('|'), specsArray, itemObj.data(/}}\s*\w*?data\s*=.*?sv[a-z0-9]{3}:.*?{{/img), miMods, setFlags );
+ };
+ };
+ };
+
+ for (let modRow = SaveMods.table[1]; !_.isUndefined(modName = SaveMods.tableLookup( fields.SaveMod_name, modRow, false )); modRow++) {
+ if (modName === '-') continue;
+ let curRound = parseInt(SaveMods.tableLookup(fields.SaveMod_curRound,modRow)) || 0,
+ toRound = parseInt(SaveMods.tableLookup(fields.SaveMod_round,modRow)) || 0,
+ diff = state.initMaster.round - curRound;
+ if (diff < 0 && !isNaN(toRound) && toRound !== 0) toRound += diff;
+ curRound += diff;
+ let saveCount = SaveMods.tableLookup(fields.SaveMod_saveCount,modRow);
+ if ((saveCount !== '' && saveCount <= 0) || (!isNaN(toRound) && toRound > 0 && toRound < state.initMaster.round)) {
+ SaveMods.addTableRow(modRow);
+ continue;
+ } else if (diff !== 0 && !isNaN(toRound) && toRound > 0) {
+ SaveMods.tableSet(fields.SaveMod_curRound,modRow,curRound);
+ SaveMods.tableSet(fields.SaveMod_round,modRow,toRound);
+ };
+ let spellName = SaveMods.tableLookup(fields.SaveMod_spellName,modRow);
+ [miMods,setFlags] = scanForSaves( spellName, modName, spellName.toLowerCase().split('|'), [['','','','','']], [['['+SaveMods.tableLookup(fields.SaveMod_saveSpec,modRow)+']']], miMods, setFlags );
+ };
+
+ _.each(miMods, function(s,c) {
+ mods = _.mapObject(mods, function(v,k) {
+ return (_.isUndefined(s[k]) ? v : (setFlags[k] ? s[k] : (v + s[k])));
+ });
+ });
+
+ _.each( saveFormat.Saves, (s,k) => {
+ LibFunctions.setAttr( charCS, s.mon, saves[s.index] );
+ LibFunctions.setAttr( charCS, s.save, saves[s.index] );
+ LibFunctions.setAttr( charCS, s.mod, mods[s.tag] );
+ });
+
+ for (let modRow = SaveMods.table[1]; !_.isUndefined(modName = SaveMods.tableLookup( fields.SaveMod_name, modRow, false )); modRow++) {
+ if (modName === '-') continue;
+ let tag = SaveMods.tableLookup( fields.SaveMod_tag, modRow ),
+ basis = SaveMods.tableLookup( fields.SaveMod_basis, modRow, false ),
+ i = SaveMods.tableLookup( fields.SaveMod_index, modRow );
+ if (_.isUndefined(mods[tag])) {
+ mods[tag] = 0;
+ setFlags[tag] = false;
+ }
+ if (!_.isUndefined(basis) && !setFlags[tag]) mods[tag] += mods[basis];
+ LibFunctions.setAttr( charCS, [SaveMods.tableLookup( fields.SaveMod_saveField, modRow ),'current'], saves[i] );
+ LibFunctions.setAttr( charCS, [SaveMods.tableLookup( fields.SaveMod_modField, modRow ),'current'], mods[tag] );
+ };
+
+ if (!silent) {
+ itemText += _.reduce(addedText, (t,i) => (t + i));
+ content +='{{Saves=';
+ let i = -1,
+ a = [];
+ _.each( saveFormat.Saves, (s,k) => {
+ if (s.index != i) {
+ content += a.join(', ');
+ a = [];
+ content += (i>0?'':'')+'**'+saves[(i=s.index)]+'** | ';
+ }
+ a.push(k+'('+(mods[s.tag]>=0?'+':'')+mods[s.tag]+')');
+ });
+ content += a.join(', ')+' | ';
+ for (let modRow = SaveMods.table[1]; !_.isUndefined(modName = SaveMods.tableLookup( fields.SaveMod_name, modRow, false )); modRow++) {
+ if (modName === '-') continue;
+ let tag = SaveMods.tableLookup( fields.SaveMod_tag, modRow ),
+ index = SaveMods.tableLookup( fields.SaveMod_index, modRow );
+ content += '**'+saves[index]+'** | '+modName+'('+(mods[tag]>=0?'+':'')+mods[tag]+') | ';
+ };
+
+ content += ' }}';
+ content += '{{Attribute Checks=';
+ _.each( saveFormat.Attributes, (a,k) => content += '**'+LibFunctions.attrLookup(charCS,a.save)+'** | '+k+'('+(mods[a.tag]>=0?'+':'')+mods[a.tag]+') | ');
+ content +=' }}'
+ + ((selected.length == 1) ? itemText : '');
+ };
+ } catch (e) {
+ sendCatchError('RPGM Library',null,e,'RPGM Library handleCheckSaves()');
+ content = '';
+ } finally {
+ setTimeout(() => {
+ resolve(content);
+ }, 1);
+ };
+ });
+ };
+
+ async function checkAllSaves( args, selected, senderId, silent ) {
+ try {
+ var who = LibFunctions.sendToWho(null,senderId);
+
+ if (attkMenu = (args && args[0])) {
+ selected = [];
+ selected.push(getObj('graphic',args[0]));
+ }
+ let nomenu = args && ((args[2] || '') === 'nomenu');
+
+ for (const token of selected) {
+ if (msg && msg.length) msg += '\n'+who;
+ msg += await checkThisSave( attkMenu, token, senderId, silent, selected );
+ };
+
+ if (!silent && !nomenu && (attkMenu || (args && args[1]))) {
+ if (!msg) msg = '&{template:'+fields.defaultTemplate+'}';
+ msg += '{{desc=[Return to Menu]('+(attkMenu ? ('!attk --button '+(args[1] || 'SAVES')+'|'+args[0]) : ('!cmd --button '+args[1]))+')}}';
+ }
+ if (!silent) {
+ LibFunctions.sendResponse( charCS, msg, senderId );
+ } else {
+ clearWaitTimer(senderId);
+ }
+ return;
+ } catch (e) {
+ sendCatchError( 'RPGM Library', msg_orig[senderId], e);
+ }
+ };
+
+ checkAllSaves( args, selected, senderId, silent );
+ 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;
+ }
+
+/* ------------------------------------------------------------ Configuration ------------------------------------------------ */
+
+ /**
+ * Get the configuration for the player who's ID is passed in
+ * or, if the config is passed back in, set it in the state variable
+ **/
+
+ LibFunctions.getSetPlayerConfig = function( playerID, configObj ) {
+
+ if (!state.MagicMaster.playerConfig[playerID]) {
+ state.MagicMaster.playerConfig[playerID]={};
+ }
+ if (!_.isUndefined(configObj)) {
+ state.MagicMaster.playerConfig[playerID] = configObj;
+ };
+ return state.MagicMaster.playerConfig[playerID];
+ };
+
+ /*
+ * Make a configuration menu to allow the DM to select:
+ * - strict mode: follow the rules precisely,
+ * - house rules mode: follow "old fogies" house rules
+ * - no restrictions: allow anything goes
+ */
+
+ LibFunctions.makeConfigMenu = function( args, msg='' ) {
+
+ var configButtons = function( flag, txtOn, cmdOn, txtOff, cmdOff ) {
+ const liveButton = (txt) =>''+txt+' | ',
+ selButton = (txt,cmd) => ''+txt+' | ';
+ var buttons = (flag ? (selButton(txtOn,cmdOn)+liveButton(txtOff)) : (liveButton(txtOn)+selButton(txtOff,cmdOff)));
+// + (flag ? ('['+txtOn+']('+cmdOn+')'+txtOff+'')
+// : (''+txtOn+' | ['+txtOff+']('+cmdOff+')'))
+ return buttons;
+ };
+
+ var content = '&{template:'+fields.menuTemplate+'}{{name=Configure RPGMaster}}{{subtitle=AttackMaster}}'
+ + (msg.length ? '{{ ='+msg+'}}' : '')
+ + '{{desc=Select which configuration you wish for this campaign using the toggle buttons below.}}'
+ + '{{desc1=';
+
+ content += ('undefined' !== typeof MagicMaster ? ('Menus | '+configButtons(state.MagicMaster.fancy, 'Plain menus', '!magic --config fancy-menus|false', 'Fancy menus', '!magic --config fancy-menus|true')+' ') : '');
+ if ('undefined' !== typeof attackMaster) {
+ content += 'Player Targeted Attks | '+configButtons(!state.attackMaster.weapRules.dmTarget, 'Not Allowed', '!attk --config dm-target|true', 'Allowed by All', '!attk --config dm-target|false')+' '
+ + 'Allowed weapons | '+configButtons(state.attackMaster.weapRules.allowAll, 'Restrict Usage', '!attk --config all-weaps|false', 'All Can Use Any', '!attk --config all-weaps|true')+' '
+ + (state.attackMaster.weapRules.allowAll ? '' : ('Restrict weapons | '+configButtons(!state.attackMaster.weapRules.classBan, 'Strict Denial', '!attk --config weap-class|true', 'Apply Penalty', '!attk --config weap-class|false')+' '))
+ + 'Weapon Speed | '+configButtons(!state.attackMaster.weapRules.initPlus, 'Plus affects speed', '!attk --config weap-plus|true', 'Magic Plus Ignored', '!attk --config weap-plus|false')+' '
+ + 'Critical Rolls | '+configButtons(!state.attackMaster.weapRules.criticals, 'Always hit/miss', '!attk --config criticals|true', 'Calculate hit/miss', '!attk --config criticals|false')+' '
+ + 'Natural Max Min Rolls | '+configButtons(!state.attackMaster.weapRules.naturals, 'Always hit/miss', '!attk --config naturals|true', 'Calculate hit/miss', '!attk --config naturals|false')+' '
+ + 'Allowed Armour | '+configButtons(state.attackMaster.weapRules.allowArmour, 'Strict Denial', '!attk --config all-armour|false', 'All Can Use Any', '!attk --config all-armour|true')+' '
+ + 'Non-Prof Penalty | '+configButtons(!state.attackMaster.weapRules.prof, 'Class Penalty', '!attk --config prof|true', 'Character Sheet', '!attk --config prof|false')+' '
+ + 'Ranged Mastery | '+configButtons(state.attackMaster.weapRules.masterRange, 'Not Allowed', '!attk --config master-range|false', 'Mastery Allowed', '!attk --config master-range|true')+' '
+ + 'Rogue Skills | '+configButtons(state.attackMaster.thieveCrit, 'No Critical', '!attk --config rogue-crit|false', 'Critical Success', '!attk --config rogue-crit|true')+' '
+ + ((state.attackMaster.thieveCrit > 0) ? ('Rogue Crit Value | '+configButtons(state.attackMaster.thieveCrit>1, 'Critical = 1%', '!attk --config rogue-crit-val|false', 'Critical = 5%', '!attk --config rogue-crit-val|true')+' ') : '');
+ }
+ if ('undefined' !== typeof MagicMaster) {
+ content += 'Specialist Wizards | '+configButtons(!state.MagicMaster.spellRules.specMU, 'Specified in Rules', '!magic --config specialist-rules|true', 'Allow Any Specialist', '!magic --config specialist-rules|false')+' '
+ + 'Spells per Level | '+configButtons(!state.MagicMaster.spellRules.strictNum, 'Strict by Rules', '!magic --config spell-num|true', 'Allow to Set Misc', '!magic --config spell-num|false')+' '
+ + 'Spell Schools | '+configButtons(state.MagicMaster.spellRules.allowAll, 'Strict by Rules', '!magic --config all-spells|false', 'All Can Use Any', '!magic --config all-spells|true')+' '
+ + 'Powers by Level | '+configButtons(state.MagicMaster.spellRules.allowAnyPower, 'Strict by Rules', '!magic --config all-powers|false', 'All Can Use Any', '!magic --config all-powers|true')+' '
+ + 'Custom Objects | '+configButtons(!state.MagicMaster.spellRules.denyCustom, 'External / GM Defined', '!magic --config custom-spells|true', 'All Items Allowed', '!magic --config custom-spells|false')+' '
+ + 'Auto-Hide Items | '+configButtons(state.MagicMaster.autoHide, 'GM Hide Manually', '!magic --config auto-hide|false', 'Auto-Hide if Possible', '!magic --config auto-hide|true')+' '
+ + 'Reveal Hidden Items | '+configButtons(state.MagicMaster.reveal, 'Reveal Manually', '!magic --config reveal|false', 'Reveal on Use', '!magic --config reveal|true')+' '
+ + 'Action Buttons | '+configButtons(state.MagicMaster.viewActions, 'Grey on View', '!magic --config view-action|false', 'Active on View', '!magic --config view-action|true')+' '
+ + 'Alphabetic Lists | '+configButtons(!state.MagicMaster.alphaLists, 'Alphabetic', '!magic --config alpha-lists|true', 'Not Alphabetic', '!magic --config alpha-lists|false')+' '
+ + 'Skill-Based Chance | '+configButtons(!state.MagicMaster.gmRolls, 'GM rolls', '!magic --config gm-rolls|true', 'Player rolls', '!magic --config gm-rolls|false')+' ';
+ }
+ content += ('undefined' !== typeof CommandMaster ? ('[Set Default Token Bars](!cmd --button AB_ASK_TOKENBARS|) | ') : '')
+ + ' }}';
+ LibFunctions.sendFeedback( content );
+ return;
+ };
+
+/* -------------------------------------------------- Code stubs for alternate versions -------------------------------------- */
+
+ LibFunctions.creatureAttkDefs = function() {};
+ LibFunctions.creatureWeapDefs = function() {};
+ LibFunctions.updateClassLevel = function() {};
+ LibFunctions.displayClassLevel = function() {};
+
+/* --------------------------------------------------- End of Library Functions ---------------------------------------------------- */
+
+
+/* ---------------------------------------------------- Finish Initialisation ---------------------------------------------- */
+
+ LibFunctions.sendFeedback( waitMsgDiv+'Please wait while RPGMaster initialises...' );
+ apis.magic = ('undefined' !== typeof MagicMaster);
+ apis.attk = ('undefined' !== typeof attackMaster);
+ apis.init = ('undefined' !== typeof initMaster);
+ DBindex = undefined;
+
+ if (_.isUndefined(state.RPGMaster)) state.RPGMaster = {};
+ if (_.isUndefined(state.RPGMaster.tokenFields)) {
+ state.RPGMaster.tokenFields = [fields.AC[0],fields.Thac0_base[0],fields.HP[0]];
+ };
+ if (_.isUndefined(state.MagicMaster)) state.MagicMaster = {};
+ if (_.isUndefined(state.MagicMaster.spellRules)) state.MagicMaster.spellRules = {};
+
+ setTimeout( del_Old_DBs, 5000 );
+
+ // RED: v1.036 create help handouts from stored data
+ setTimeout( () => LibFunctions.updateHandouts(handouts,true,findTheGM()),300);
+ setTimeout( () => displayReleaseNotesLink(), 5000 );
+ setTimeout( () => LibFunctions.sendAPI('!token-mod --api-as '+findTheGM()+' --config players-can-ids|on',findTheGM()), 10000);
+ }
+ }
+
+ const handleChatMessage = (msg) => {
+ try {
+ var preamble, targetid,
+ playerid = msg.playerid;
+
+ msg_orig[playerid] = msg;
+
+ 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);
+ return;
+ }
+ 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) ? targetid : targetObjs[0].id;
+ }
+ }
+ let newMsg = Object.create(msg);
+ newMsg = processInlinerolls(newMsg);
+ const template = newMsg.match(/^([^{]*)({{[^]*}}).*?$([^]*)/im);
+ switch (msg.type.toLowerCase()) {
+ case 'emote':
+ preamble = '/em';
+ break;
+ case 'desc':
+ preamble = '/desc';
+ break;
+ case 'whisper':
+ preamble = '/w "'+msg.target_name+'"';
+ break;
+ default:
+ preamble = '';
+ break;
+ }
+ if (/^\s*\/i.test(template[1])) preamble += ' '+template[1]; else if (template[1].trim().length) log('RPGM output parser: extra 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');
+ LibFunctions.sendCatchError('RPGMaster Library',msg_orig[playerid],e);
+ }
+ };
+
+ 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),
+ sendMsgToWho: (...a) => LibFunctions.sendMsgToWho(...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),
+ sendCatchError: (...a) => LibFunctions.sendCatchError(...a),
+ sendParsedMsg: (...a) => LibFunctions.sendParsedMsg(...a),
+ sendGMquery: (...a) => LibFunctions.sendGMquery(...a),
+ sendWait: (...a) => LibFunctions.sendWait(...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),
+ findThePlayer: (...a) => LibFunctions.findThePlayer(...a),
+ findCharacter: (...a) => LibFunctions.findCharacter(...a),
+ fixSenderId: (...a) => LibFunctions.fixSenderId(...a),
+ calcAttr: (...a) => LibFunctions.calcAttr(...a),
+ rollDice: (...a) => LibFunctions.rollDice(...a),
+ evalAttr: (...a) => LibFunctions.evalAttr(...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),
+ parseClassDB: (...a) => LibFunctions.parseClassDB(...a),
+ handleCheckSaves: (...a) => LibFunctions.handleCheckSaves(...a),
+ handleCheckWeapons: (...a) => LibFunctions.handleCheckWeapons(...a),
+ getHandoutIDs: (...a) => LibFunctions.getHandoutIDs(...a),
+ classAllowedItem: (...a) => LibFunctions.classAllowedItem(...a),
+ parseData: (...a) => LibFunctions.parseData(...a),
+ parseStr: (...a) => LibFunctions.parseStr(...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),
+ creatureAttkDefs: (...a) => LibFunctions.creatureAttkDefs(...a),
+ creatureWeapDefs: (...a) => LibFunctions.creatureWeapDefs(...a),
+ getSetPlayerConfig: (...a) => LibFunctions.getSetPlayerConfig(...a),
+ makeConfigMenu: (...a) => LibFunctions.makeConfigMenu(...a),
+ displayClassLevel: (...a) => LibFunctions.displayClassLevel(...a),
+ updateClassLevel: (...a) => LibFunctions.updateClassLevel(...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 dc7409c90..a342b6a2a 100644
--- a/RPGMlibrary AD+D2e/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/libRPGMaster2e.js
@@ -85,13 +85,14 @@ API_Meta.libRPGMaster={offset:Number.MAX_SAFE_INTEGER,lineCount:-1};
* operators for ceil(...) and floor(...). Grey out database item action buttons on "view"
* (toggled by config button)
* v3.5.1 03/08/2024 Changed thief detect noise skill to be on a configurable GM roll.
+ * v3.5.2 14/09/2024 Fixed evalAttr() to correctly deal with attribute [...] descriptors
**/
const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
'use strict';
- const version = '3.5.1';
+ const version = '3.5.2';
API_Meta.libRPGMaster.version = version;
- const lastUpdate = 1717750563;
+ const lastUpdate = 1726328386;
const schemaVersion = 0.1;
log('now in seconds is '+Date.now()/1000);
@@ -3625,35 +3626,28 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
type:'spells',
avatar:'https://s3.amazonaws.com/files.d20.io/images/163483347/1CLiNzi4jlxXK1-lVr7MTQ/max.png?1599726214',
version:8.02,
- db:[{name:'Banishment',type:'muspelll7',ct:'7',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nBanishment\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Abjuration}}Specs=[Banishment,MUspellL7,1H,Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[20]] yards}}{{duration=Instantaneous}}{{aoe=[60ft radius](!rounds --aoe @{selected|token_id}|circle|yards|20|40||magic)}}{{save=Special}}{{reference=PHB p182}}SpellData=[w:Banishment,lv:7,sp:7,gp:10,cs:VSM]{{effects=Enables the caster to force some extraplanar creature out of the caster\'s home plane. The effect is instantaneous, and the subject cannot come back without some special summoning or means of egress from its own plane to the one from which it was banished. Up to 2 Hit Dice or levels of creature per caster level can be banished.}}{{hide1=The caster must both name the type of creature(s) to be sent away and give its name and title as well, if any. In any event, the creature\'s magic resistance must be overcome for the spell to be effective.\nThe material components of the spell are substances harmful, hateful, or opposed to the nature of the subject(s) of the spell. For every such substance included in the casting, the subject creature(s) loses 5% from its magic resistance and suffers a -2 penalty to its saving throw vs. spell. For example, if iron, holy water, sunstone, and a sprig of rosemary were used in casting a banishment upon a being that hates those things, its saving throw versus the spell would be made with a -8 penalty (four substances times the factor of -2). Special items, such as hair from the tail of a ki-rin or couatl feathers, could also be added to change the factor to -3 or -4 per item. In contrast, a titan\'s hair or mistletoe blessed by a druid might lower the factor to -1 with respect to the same creature. If the subject creature successfully rolls its saving throw vs. spell, the caster is stung by a backlash of energy, suffers 2d6 points of damage, and is stunned for one round.}}'},
- {name:'Bigbys-Grasping-Hand',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nBigby\'s Grasping Hand\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Evocation}}Specs=[Bigbys Grasping Hand,MUspellL7,1H,Evocation]{{components=V,S,M}}{{time=[[7]]}}{{range=[[10*@{selected|mu-casting-level}]] yards}}{{duration=[[@{selected|mu-casting-level}]] rounds}}{{aoe=Special}}{{save=None}}{{Use=[Create hand](!rounds --target-nosave caster|@{selected|token_id}|Bigbys-Grasping-hand|@{selected|mu-casting-level}|-1|They\'ve given you a Big Grasping Hand! HP@{selected|hp|max}, AC0|fist)}}{{reference=PHB p183}}SpellData=[w:Bigbys Grasping Hand,lv:7,sp:7,gp:0.1,cs:VSM]{{effects=*Bigby\'s grasping hand* is a superior version of the 6th-level spell *Bigby\'s forceful hand*. It creates a man-sized (5 feet) to gargantuan-sized (21 feet) hand that appears and grasps a creature designated by the caster, regardless of what the spellcaster does or how the opponent tries to escape it. The grasping hand has an Armor Class of 0, has [[@{selected|hp|max}]] HP, and vanishes when destroyed.}}{{hide1=The grasping hand can hold motionless a creature or object of up to 1,000 pounds weight, slow movement to 10 feet per round if the creature weighs between 1,000 and 4,000 pounds, or slow movement by 50% if the creature weighs up to 16,000 pounds. The hand itself inflicts no damage. The caster can order it to release a trapped opponent or can dismiss it on command.}}{{materials=A leather glove, costing 1gp and reusable 10 times}}'},
- {name:'Cacodemon',type:'muspelll7',ct:'360',charge:'uncharged',cost:'15',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nCacodemon\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning}}Specs=[Cacodemon,MUspellL7,1H,Conjuration-Summoning]{{components=V, S, M}}{{time=Up to [[6]] hours}}{{range=[[30]]yards}}{{duration=Special}}{{aoe=Creature Summoned}}{{save=Special}}{{reference=AD\\ampD1e PHB p86}}SpellData=[w:Cacodemon,lv:7,sp:360,gp:15,cs:SM]{{effects=Summons a powerful demon of type IV, V, or VI depending on the demon\'s name being known to the Magic User.}}{{hide1=This perilous exercise in dweomercraeft summons up a powerful demon of type IV, V, or VI, depending upon the demon\'s name being known to the magic- user. Note thti this spell is not of sufficient power to bring a demon of greater power, and lesser sorts are not called as they have no known names. In any event, the spell caster must know the name of the type IV, V, or VI demon he or she is summoning. As the spetl name implies, the demon so summoned is most angry and evilly disposed. The spell caster musi be within a circle of protection {or a thaumoturgic triangle with *protection from evil*) and the demon confined within a pentagram (circled pentangle) if he or she is to avoid being slain or carried off by the summoned cocodemon. The summoned demon can be treated with as follows:\n1) The magic-user can require the monster to perform a desired course of action by force of threat and pain of a *spiritwrack* spell (q.v), allowing freedom whenever the demon performs the full extent of the service, and forcing the demon to pledge word upon It, This is exceedingly dangerous, as a minor error in such a bargain will be seized upon by the monster to reverse the desired outcome or simply to kill and devour the summoner. Furthermore, the demon will bear great enmity for the magic-user forever over such forced obedience, so the spell caster had better be most powerful and capable.\n2) By tribute of fresh human blood and the promise of 1 or more human sacrifices, the summoner can bargain with the demon for willing service. Again, the spell caster is welI advised to have ample protection and power lo defend himself or herself, as the demon might decide the offer is insufficient — or it is easier to enjoy the summoner\'s slow death — and decide not to accept the bargain as offered. Although the demon will have to abide by a pledge, as his name is known, he will have to hold only to the exact word of the arrangement, not to the spirit of the agreement. On the other hand, only highly evil magic-users are likely to attempt to strike such a bargain, and the summoned cocodemon might be favorably disposed towards such a character, especially if he or she is also chaotic.\n3} The summoned demon can be the object of a *trap the soul* spell. In this cose, the magic-user will not speak with or bargain for the demon\'s services, although the cocodemon might be eager to reach an accord with the dweomercraefter before he is forced into imprisonment. The trapping of the demon is risky only if proper precautions have not been token, for failure to confine the monster usually means only that it is able to escope to its own plane. Once trapped, the demon must remain imprisoned until the possessor of his object of confinement breaks it and frees him, ond this requires one service from the now loosed monster. If the individual(s) freeing the demon fails to demand a service when the monster asks what is required of him, the demon is under no constraint not to slay the liberator(s) on the spot, but if a service is required, the creature must first do his best to perform it and then return to the Abyss.\nThe duration of service of any demon must be limited unless the demon is willing to serve for an extended period. Any required course of action or service which effectively requires an inordinate period of time to perform, or is impossible to perform, is 50% likely to free the demon from his obligations and enable him to be unconstrained in his vengeance upon the spell caster if he or she is not thereafter continually protected, for a demon so freed can remain on the plane it was summoned to for as long as 666 days.\nThe demon summoned will be exceptionally strong, i.e. 8 hit points per hit die. Casting Time is 1 hour per type (numeric) of the demon to be summoned, If there is any interruption during this period, the spell fails. If there is an interruption while the cocodemon is summoned, it is 10% probable that it will be able to escape its boundaries and attack the magic-user, this percentage rising cumulatively each round of continued interruption.\nEach demon is entitled to a saving throw versus this summoning spell, if a score higher than the level of the magic-user summoning is rolled with 3d6 {2d10 with respect a type VI demons), that particular spell failed to bring the desired demon. When this occurs, it is certain that the named demon is imprisoned or destroyed or the name used was not perfectly correct, so the spell caster will have to call upon another name to bring forth a cocodemon.}}{{materials=5 flaming black candles (1gp each); a brazier of hot coals on which must be burned sulphur, bat hairs, lard, soot, mercuric-nitric acid crystals, mandrake root, alcohol, and a parchment with the demon\'s name inscribed within a pentangle (total value 10gp); and a dish with mammal (preferably human) blood placed inside the area where the cocodemon is to be held.}}'},
- {name:'Charm-Plants',type:'muspelll7',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nCharm Plants\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Enchantment-Charm}}Specs=[Charm Plants,MUspellL7,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[1]] turn}}{{range=[[30]] yards}}{{duration=Permanent}}{{aoe=[10 x 30ft](!rounds --aoe @{selected|token_id}|rectangle|feet|90|30|10|magic)}}{{save=Negates}}{{reference=PHB p183}}SpellData=[w:Charm Plants,lv:7,sp:100,gp:0,cs:VSM]{{effects=Bring under command vegetable life forms and communicate with them. }}{{hide1=These plants obey instructions to the best of their ability. The spell will charm plants in a 30-foot x 10-foot area. While the spell does not endow the vegetation with new abilities, it does enable the wizard to command the plants to use whatever they have in order to fulfill his instructions. If the plants in the area of effect do have special or unusual abilities, these are used as commanded by the wizard.\nFor example, this spell can generally duplicate the effects of the 1st-level priest spell [*entangle*](!magic --display-ability @{selected|token_id}|PR-Spells-DB|entangle), if the caster desires. The saving throw applies only to intelligent plants, and it is made with a -4 penalty to the die roll.}}{{materials=A pinch of humus, a drop of water, and a twig or leaf (no cost)}}'},
- {name:'Control-Undead',type:'muspelll7',ct:'10',charge:'uncharged',cost:'0.02',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nControl Undead\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Necromancy}}Specs=[Control Undead,MUspellL7,1H,Necromancy]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[60]] feet}}!setattr --silent --charid @{selected|character_id} --spell-duration|{{duration=[[3d4+@{selected|mu-casting-level}]] rounds}}!!!{{aoe=[20HD or 6 undead](!rounds --target-save area|@{selected|token_id}|\\amp#64;{target|Which Undead do you want to control?|token_id}|Control-undead|\\amp#64;{selected|spell-duration}|-1|This undead creature is controlled by @{selected|character_name}|padlock)}}{{save=Special}}{{reference=PHB p183}}{{Use=As each undead is individually targeted, the GM will need to assess success and confirm or reject the effect, if necessary making a saving throw}}SpellData=[w:Control Undead,lv:7,sp:10,gp:0.02,cs:VSM]{{effects=Select one point within range of the spell. Those undead nearest to this point are controlled, until either [[@{selected|mu-casting-level}]] Hit Dice of undead to a max of six undead are affected. }}{{hide1=Undead with 3 Hit Dice or less are automatically controlled. Those of greater Hit Dice are allowed a saving throw vs. spell, which, if successful, negates the attempt to control that creature. Regardless of the success or failure of the saving throw, each creature required to make a check counts toward the Hit Dice limit of the spell.\nThose creatures under the control of the wizard can be commanded by the caster if they are within hearing range. There is no telepathic communication or language requirement between the caster and the controlled undead. Even if communication is impossible, the controlled undead do not attack the spellcaster. At the end of the spell, the controlled undead revert to their normal behaviors. Those not mindless will remember the control exerted by the wizard.}}{{materials=A small piece each of bone and raw meat, cost 2cp}}'},
- {name:'Delayed-Blast-Fireball',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0.02',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nDelayed Blast Fireball\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Evocation}}Specs=[Delayed Blast Fireball,MUspellL7,1H,Evocation]{{components=V,S,M}}{{time=[[7]]}}{{range=[[100+(10*@{selected|mu-casting-level})]] yards}}{{duration=Delay up to 5 rounds}}{{aoe=20ft radius}}{{save=Halves}}{{damage=[[{10, @{selected|mu-casting-level}}kl1]] + [[{10, @{selected|mu-casting-level}}kl1]]d6}}{{damagetype=Fire}}{{reference=PHB p183}}{{Use=Click [Delay Fireball](!rounds (!rounds --aoe @{selected|token_id}|circle|feet|[[300+(30*@{selected|mu-casting-level})]]|3||fire||@{selected|token_id}|caster|Delayed-blast-fireball|\\amp#63;{What delay in rounds?|5|4|3|2|1}|-1|Waiting for the firball to go off|stopwatch), specify the delay when asked, then mark the area of effect by moving the crosshair and confirming to place the *fireball seed*. Once the fireball goes off, an *explode* button and a *damage* button will be displayed to the caster to enact the effect}}SpellData=[w:Delayed Blast Fireball,lv:7,sp:7,gp:0.02,cs:VSM]{{effects=Creates a fireball, with a +1 bonus to each of its dice of damage, which releases its blast anytime from instantly to five rounds later, according to the command given by the wizard. In other respects, the spell is the same as the 3rd-level spell [*fireball*](!magic --display-ability @{selected|token_id}|MU-Spells-DB|Fireball).}}{{materials=A tiny ball of bat guano and sulphur, cost 2cp}}'},
- {name:'Drawmijs-Instant-Summons',type:'muspelll7',ct:'1',charge:'uncharged',cost:'5000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nDrawmijs Instant Summons\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning}}Specs=[Drawmijs-Instant-Summons,MUspellL7,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=[[1]]}}{{range=infinite + special}}{{duration=Instantaneous}}{{aoe=1 small object}}{{save=None}}{{reference=PHB p183}}SpellData=[w:Drawmijs-Instant-Summons,lv:7,sp:1,gp:5000,cs:VSM]{{effects=Teleports some desired item from virtually any location directly to his hand.}}{{hide1=The single object can be no longer in any dimension than a sword, can have no more weight than a shield (about eight pounds), and must be\nnonliving.\nTo prepare this spell, the wizard must hold a gem of not less than 5,000 gp value in his hand and utter all but the final word of the conjuration. At some point in the future, he must crush the gem and utter the final word. The desired item is then transported instantly into the spellcaster\'s right or left hand, as he desires.\nThe item must have been previously touched during the initial incantation and specifically named; only that particular item is summoned by the spell. During the initial incantation, the gem becomes magically inscribed with the name of the item to be summoned. The inscription is invisible and unreadable, except by means of a read magic spell, to all but the wizard who cast the summons.\nIf the item is in the possession of another creature, the spell does not work, and the caster knows who the possessor is and roughly where he, she, or it is located when the summons is cast. Items can be summoned from other planes of existence, but only if such items are not in the possession (not necessarily the physical grasp) of another creature. For each level of experience above the 14th, the wizard is able to summon a desired item from one plane farther removed from the plane he is in at the time the spell is cast (one plane away at 14th level, two planes away at 15th, etc.). Thus, a wizard of 16th level could cast the spell even if the desired item was on the second layer of one of the Outer Planes, but at 14th level the wizard would be able to summon the item only if it were no farther than one of the Inner Planes, the Ethereal Plane, or the Astral Plane (see the Planescape Campaign Setting boxed set). Note that special wards or barriers, or factors that block the teleport or plane shift spells, may also block the operation of this spell. Objects in Leomund\'s secret chest cannot be recovered by using this spell. \nNote: If the item is wizard marked, it can be summoned from anywhere on the same plane unless special local conditions apply. Furthermore, the details of the location of the item are more specific, and the item is more easily traceable with other types of scrying magic.}}{{materials=A gem of not less than 5,000 gp value}}'},
- {name:'Duo-Dimension',type:'muspelll7',ct:'7',charge:'uncharged',cost:'750',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nDuo-Dimension\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Duo-Dimension,MUspellL7,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[0]]}}{{duration=[[[3+@{selected|mu-casting-level}]] rounds](!rounds --target-nosave caster|@{selected|token_id}|Duo-dimension|[[3+@{selected|mu-casting-level}]]|-1|Becomes 2-dimensional like paper|three-leaves)}}{{aoe=The caster}}{{save=None}}{{reference=PHB p184}}SpellData=[w:Duo-Dimension,lv:7,sp:7,gp:750,cs:VSM]{{effects=Causes the caster to have only two dimensions, height and width, with no depth. Invisible when turned sideways.}}{{hide1=This invisibility can be detected only by means of a *true seeing* spell or similar methods. In addition, the duodimensional wizard can pass through the thinnest of spaces as long as these have the proper height--going through the space between a door and its frame is a simple matter. The wizard can perform all actions normally. He can turn and become invisible, move in this state, and appear again next round and cast a spell, disappearing on the following round.\nNote that when turned, the wizard cannot be affected by any form of attack, but when visible, he is subject to double the amount of damage normal for an attack form; for example, a dagger thrust would inflict 2d4 points of damage if it struck a duodimensional wizard. Furthermore, the wizard has a portion of his existence in the Astral Plane when the spell is in effect, and he is subject to possible notice by creatures there. If noticed, it is 25% probable that the wizard is pulled entirely into the Astral Plane by any attack from an astral creature. Such an attack (and any subsequent attack received on the Astral Plane) inflicts normal damage.\nThe material components of this spell are a flat ivory likeness of the spellcaster (which must be of finest workmanship, gold filigreed, and enameled and gem-studded at an average cost of 500 to 1,000 gp) and a strip of parchment. As the spell is uttered, the parchment is given half a twist and joined at the ends. The figurine is then passed through the parchment loop, and both disappear forever.}}{{materials=A flat ivory likeness of the spellcaster (which must be of finest workmanship, gold filigreed, and enamelled and gem-studded at an average cost of 500 to 1,000 gp) and a strip of parchment}}'},
- {name:'Finger-of-Death',type:'muspelll7',ct:'5',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nFinger of Death\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Necromancy}}Specs=[Finger of Death,MUspellL7,1H,Necromancy]{{components=V,S}}{{time=[[5]]}}{{range=[[[60]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|120||dark|true)}}{{duration=Permanent}}{{aoe=1 creature}}{{save=Negates}}{{reference=PHB p184}}SpellData=[w:Finger of Death,lv:7,sp:5,gp:500,cs:VS]{{effects=Snuffs out the victim\'s life force. A creature successfully saving still receives [2d8+1](!\\amp#13;\\amp#47;r 2d8+1) points of damage. If the subject dies of damage, no internal changes occur and the victim can then be revived normally.}}{{hide1=If successful, the victim can be neither raised nor resurrected. In addition, in human subjects the spell initiates changes to the body such that after three days the caster can, by means of a special ceremony costing not less than 1,000 gp plus 500 gp per body, animate the corpse as a juju zombie under the control of the caster. The changes can be reversed before animation by a limited wish or similar spell cast directly upon the body, and a full wish restores the subject to life.\nThe caster utters the finger of death spell incantation, points his index finger at the creature to be slain, and unless the victim succeeds in a saving throw vs. spell, death occurs.}}'},
- {name:'Forcecage',type:'muspelll7',ct:'3',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nForcecage\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Evocation}}Specs=[Forcecage,MUspellL7,1H,Evocation]{{components=V,S, special}}{{time=[[3]]}}{{range=[[10*ceil(@{selected|mu-casting-level}/2)]] yards}}{{duration=[[[6+@{selected|mu-casting-level}]] turns](!rounds --target-nosave multi|@{selected|token_id}|Forcecage|[[6+@{selected|mu-casting-level}]]|-1|Containing creatures in a Forcecage|fishing-net)}}{{aoe=[20ft. cube](!rounds --aoe @{selected|token_id}|square|feet|[[60*ceil(@{selected|mu-casting-level}/2)]]|20||magic)}}{{save=None}}{{reference=PHB p184}}{{Use=Show the area of effect, and then use the *duration* button - select all the creatures in the area and press the *add status changes* button in the chat window. The GM can remove the status for creatures that make *magic resistance* and escape using the *maint menu*}}SpellData=[w:Forcecage,lv:7,sp:3,gp:1000,cs:VSM]{{effects=Bring into being a cube of force, but it is unlike the magical item of that name in one important respect: The forcecage does not have solid walls of force; it has alternating bands of force with 1/2-inch gaps between.}}{{hide1=Thus, it is truly a cage, rather than an enclosed space with solid walls. Creatures within the area of effect of the spell are caught and contained unless they are able to pass through the openings--and, of course, all spells and breath weapons can pass through the gaps in the bars of force of the forcecage.\nA creature with magic resistance has a single attempt to pass through the walls of the cage. If the resistance check is successful, the creature escapes. If it fails, the creature is caged. Note that a successful check does not destroy the cage, nor does it enable other creatures (save familiars) to flee with the escaping creature. The forcecage is also unlike the solid-walled protective device, cube of force, in that it can be gotten rid of only by means of a dispel magic spell or by the expiration of the spell.\nBy means of special preparation at the time of memorization, a *forcecage* spell can be altered to a [*forcecube*](!magic --display-ability @{selected|token_id}|MU-Spells-DB|Forcecube) spell.\nAlthough the actual casting of either application of the spell requires no material component, the study required to commit it to memory does demand that the wizard powder a diamond of at least 1,000 gp value, using the diamond dust to trace the outlines of the cage or cube he desires to create via spellcasting at some later time. Thus, in memorization, the diamond dust is employed and expended, for upon completion of study, the wizard must then toss the dust into the air and it will disappear.}}{{materials=A diamond of at least 1,000gp value}}'},
- {name:'Forcecube',type:'muspelll7',ct:'4',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nForcecube\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Evocation}}Specs=[Forcecage,MUspellL7,1H,Evocation]{{components=V,S, special}}{{time=[[4]]}}{{range=[[10*ceil(@{selected|mu-casting-level}/2)]] yards}}{{duration=[[[6+@{selected|mu-casting-level}]] turns](!rounds --target caster|@{selected|token_id}|Forcecage|[[6+@{selected|mu-casting-level}]]|-1|Containing creatures in a Forcecube|fishing-net)}}{{aoe=[10ft. cube](!rounds --aoe @{selected|token_id}|square|feet|[[60*ceil(@{selected|mu-casting-level}/2)]]|10||magic)}}{{save=None}}{{reference=PHB p184}}{{Use=Show the area of effect, and then use the *duration* button - select all the creatures in the area and press the *add status changes* button in the chat window. The GM can remove the status for creatures that make *magic resistance* and escape using the *maint menu*}}SpellData=[w:Forcecage,lv:7,sp:4,gp:1000,cs:VSM]{{effects=By means of special preparation at the time of memorization, a *forcecage* spell (see separate spell) can be altered to a *forcecube* spell. The cube created is 10 feet on a side, and the spell then resembles that of a cube of force in all respects save that of the differences between a cast spell and the magic of a device, including the methods of defeating its power.}}{{hide1=Although the actual casting of either application of the spell requires no material component, the study required to commit it to memory does demand that the wizard powder a diamond of at least 1,000 gp value, using the diamond dust to trace the outlines of the cage or cube he desires to create via spellcasting at some later time. Thus, in memorization, the diamond dust is employed and expended, for upon completion of study, the wizard must then toss the dust into the air and it will disappear.}}{{materials=A diamond of at least 1,000gp value}}'},
- {name:'Limited-Wish',type:'muspelll7',ct:'10',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nLimited Wish\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning, Invocation-Evocation}}Specs=[Limited Wish,MUspellL7,0H,Conjuration-Summoning|Invocation-Evocation]{{components=V}}{{time=Special}}{{range=Unlimited}}{{duration=Special}}{{aoe=Special}}{{save=None}}{{reference=PHB p184}}SpellData=[w:Limited Wish,lv:7,sp:10,gp:0,cs:V]{{effects=It will fulfil literally, but only partially or for a limited duration, the utterance of the spellcaster.}}{{hide1=Thus, the actuality of the past, present, or future might be altered (but possibly only for the wizard unless the wording of the spell is most carefully stated) in some limited manner. The use of a limited wish will not substantially change major realities, nor will it bring wealth or experience merely by asking. The spell can, for example, restore some hit points (or all hit points for a limited duration) lost by the wizard. It can reduce opponent hit probabilities or damage, increase duration of some magical effect, cause a creature to be favorably disposed to the spellcaster, mimic a spell of 7th level or less, and so on (see the 9th-level wish spell). Greedy desires usually end in disaster for the wisher. Casting time is based on the time spent preparing the wording for the spell (clever players decide what they want to say before using the spell). Normally, the casting time is one round (most of it being taken up by deciding what to say). Casting this spell ages the caster one year per 100 years of regular life span.}}'},
- {name:'Mass-Invisibility',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0.05',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nMass Invisibility\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Illusion-Phantasm}}Specs=[Mass Invisibility,MUspellL7,1H,Mass Invisibility]{{components=V,S,M}}{{time=[[7]]}}{{range=[[10*@{selected|mu-casting-level}]] yards}}{{duration=Special}}{{aoe=[60 x 60 yards](!rounds --aoe @{selected|token_id}|square|yards|[[10*@{selected|mu-casting-level}]]|60|60|magic)}}{{save=None}}{{reference=PHB p184}}SpellData=[w:Mass Invisibility,lv:7,sp:7,gp:0.05,cs:VSM]{{effects=*Invisibility* spell for battlefield use. Can hide creatures in a 60-yard x 60-yard area: up to 400 man-sized creatures, 30 to 40 giants, or six to eight large dragons. The effect is mobile with the unit and is broken when the unit attacks. Individuals leaving the unit become visible. The wizard can end this spell upon command.}}{{materials=An eyelash and a bit of gum arabic, the former encased in the latter, costing 5cp}}'},
- {name:'Monster-Summoning-V',type:'muspelll7',ct:'6',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{}}Specs=[Monster Summoning V,MUspellL7,1H,Conjuration-Summoning]{{}}SpellData=[w:Monster Summoning V,lv:7,sp:6,gp:0.1,cs:VSM]{{}}%{MU-Spells-DB|Monster-Summoning-IV}{{title=@{selected|casting-name} casts\nMonster Summoning V\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning}}{{components=V,S,M}}{{time=[[6]]}}{{range=Special}}{{duration=[[6+@{selected|mu-casting-level}]] rounds}}{{aoe=[70yd radius](!rounds --aoe @{selected|token_id}|circle|yards|0|140||magic|true)}}{{save=None}}{{reference=PHB p185}}{{effects=[1d3](!\\amp#13;\\amp#47;r 1d3) 5th level monsters (selected by the DM from the Monster Summoning V Table in the MC) appear in the area, placed by the caster. Attack to best of their ability until caster demands attack cease, spell expires, or are slain. Disappear when slain, no morale checks. If can communicate and not attacking, caster can ask them to perform tasks.}}{{materials=A tiny bag and a small candle, worth 1sp}}'},
- {name:'Mordenkainens-Magnificent-Mansion',type:'muspelll7',ct:'7',charge:'uncharged',cost:'100',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nMordenkainens Magnificent Mansion\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration, Conjuration}}Specs=[Mordenkainens-Magnificent-Mansion,MUspellL7,1H,Alteration|Conjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[10]] yards}}{{duration=[[[@{selected|mu-casting-level}]] hours](!rounds --target-nosave caster|@{selected|token_id}|MM-mansion|[[60*@{selected|mu-casting-level}]]|-1|)}}{{aoe=[[300*@{selected|mu-casting-level}]]sq.ft. - extradimensional with a [4ft x 8ft portal](!rounds --aoe @{selected|token_id}|wall|feet|30|4|1|magic)}}{{save=None}}{{reference=PHB p185}}{{Use=Use the *duration* button to set a duration timer}}SpellData=[w:Mordenkainens Magnificent Mansion,lv:7,sp:7,gp:100,cs:VSM]{{effects=Conjures up an extradimensional dwelling, entrance to which can be gained only at a single point of space on the plane from which the spell was cast.)}}{{hide1=From the entry point, those creatures observing the area see only a faint shimmering in the air, in an area 4 feet wide and 8 feet high. The caster of the spell controls entry to the mansion, and the portal is shut and made invisible behind him when he enters. He may open it again from his own side at will. Once observers have passed beyond the entrance, they behold a magnificent foyer and numerous chambers beyond. The place is furnished and contains sufficient foodstuffs to serve a nine-course banquet to as many dozens of people as the spellcaster has levels of experience. There is a staff of near-transparent servants, liveried and obedient, to wait upon all who enter. The atmosphere is clean, fresh, and warm.\nSince the place can be entered only through its special portal, outside conditions do not affect the mansion, nor do conditions inside it pass to the plane beyond. Rest and relaxation within the place is normal, but the food is not. It seems excellent and quite filling as long as one is within the place. Once outside, however, its effects disappear immediately, and if those resting have not eaten real food within a reasonable time span, ravenous hunger strikes. Failure to eat normal food immediately results in the onset of fatigue or starvation penalties as decided by the DM.\n(It is worth mentioning that this spell has been used in conjunction with a normal portal, as well as with illusion magic. There is evidence that the design and interior of the space created can be altered to suit the caster\'s wishes.)}}{{materials=A miniature portal carved from ivory, a small piece of polished marble, and a tiny silver spoon. These cost 100gp to source, and are utterly destroyed when the spell is cast}}'},
- {name:'Mordenkainens-Sword',type:'innate-melee|muspelll7',ct:'5',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nMordenkainens Sword\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Evocation}}Specs=[Mordenkainens Sword,Innate-Melee|MUspellL7,1H,Evocation]{{components=V,S,M}}ToHitData=[w:Mordenkainens Sword,+:0,ch:19,sp:5]{{time=[[7]]}}DmgData=[w:Mordenkainens Sword,+:0,sm:5d4,L:5d6]{{range=[[[30]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||light|true)}}WeapData=[on:\\api;rounds --target-nosave caster|@{selected|token_id}|Mordenkainens-Sword|\\lbrak;\\lbrak;@{selected|mu-casting-level}\\rbrak;\\rbrak;|-1|Magical weapon in direction facing requires concentration|all-for-one,off:\\api;rounds --removetargetstatus @{selected|token_id}|Mordenkainens-Sword]{{duration=[[@{selected|mu-casting-level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p185}}SpellData=[w:Mordenkainens Sword,lv:7,sp:7,gp:500,cs:VSM]{{effects=Brings into being a shimmering, swordlike plane of force. Can mentally wield this weapon (to the exclusion of all activities other than movement), causing it to move and strike as if it were being used by a fighter.\nSelect Mordenkainen\'s Sword as a weapon when prompted after casting the spell.}}{{hide1=The basic chance for Mordenkainen\'s sword to hit is the same as the chance for a sword wielded by a fighter of half the level of the spellcaster. For example, if cast by a 14th-level wizard, the weapon has the same hit probability as a sword wielded by a 7th level fighter.\nThe sword has no magical attack bonuses, but it can hit nearly any sort of opponent, even those normally struck only by +3 weapons or those who are astral, ethereal, or out of phase. It hits any Armor Class on a roll of 19 or 20. It inflicts 5d4 points of damage to opponents of man size or smaller, and 5d6 points of damage to opponents larger than man size. It lasts until the spell duration expires, a dispel magic is used successfully upon it, or its caster no longer desires it.}}{{materials=A miniature platinum sword with a grip and pommel of copper and zinc, which costs 500 gp to construct, and which disappears after the spell\'s completion}}'},
- {name:'Phase-Door',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nPhase Door\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Phase Door,MUspellL7,0H,Alteration]{{components=V}}{{time=[[7]]}}{{range=Touch}}{{duration=[[floor(@{selected|mu-casting-level}/2)]] uses}}{{aoe=[5 x 8 x 10ft](!rounds --aoe @{selected|token_id}|rectangle|feet|0|10|5|light)}}{{save=None}}{{reference=PHB p185}}SpellData=[w:Phase Door,lv:7,sp:7,gp:0,cs:V]{{effects=The wizard attunes his body, and a section of wall is affected as if by a *passwall* spell.}}{{hide1=The phase door is invisible to all creatures save the spellcaster, and only he can use the space or passage the spell creates, disappearing when the phase door is entered, and appearing when it is exited. If the caster desires, one other creature of man size or less can be taken through the door; this counts as two uses of the door. The door does not pass light, sound, or spell effects, nor can the caster see through it without using it. Thus, the spell can provide an escape route, though certain creatures, such as phase spiders, can follow with ease. A gem of true seeing and similar magic will reveal the presence of a phase door but will not allow its use.\nThe phase door lasts for one usage for every two levels of experience of the spellcaster. It can be dispelled only by a casting of dispel magic from a higher-level wizard, or from several lower-level wizards, casting in concert, whose combined levels of experience are more than double that of the wizard who cast the spell (this is the only instance in which dispel effects can be combined).\nRumor has it that this spell has been adapted by a certain powerful wizard (or wizards) to create renewable (or permanent) portals, which may (or may not) be keyed to specific individuals (henchmen) or items (such as rings).}}'},
- {name:'Power-Word-Stun',type:'muspelll7',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nPower Word, Stun\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning}}Specs=[Power Word Stun,MUspellL7,0H,Conjuration-Summoning]{{components=V}}{{time=[[1]]}}{{range=[[[5*@{selected|mu-casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[10*@{selected|mu-casting-level}]]||magic)}}{{duration=Special}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p185}}SpellData=[w:Power Word Stun,lv:7,sp:1,gp:0,cs:V]{{effects=Any creature of the wizard\'s choice is stunned--reeling and unable to think coherently or act--for a duration dependent on its current hit points.}}{{hide1=Of course, the wizard must be facing the creature, and the creature must be within the range of 5 yards per experience level of the caster. Creatures with 1 to 30 hit points are stunned for 4d4 rounds, those with 31 to 60 hit points are stunned for 2d4 rounds, those with 61 to 90 hit points are stunned for 1d4 rounds, and creatures with over 90 hit points are not affected. Note that if a creature is weakened so that its hit points are below its usual maximum, the current number of hit points is used.}}'},
- {name:'Prismatic-Spray',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nPrismatic Spray\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Conjuration-Summoning}}Specs=[Prismatic Spray,MUspellL7,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[7]]}}{{range=[[0]]}}{{duration=Instantaneous}}{{aoe=[70 x 15ft. spray](!rounds --aoe @{selected|token_id}|cone|feet|0|70|15|magic)}}{{save=Special}}{{reference=PHB p186}}SpellData=[w:Prismatic Spray,lv:7,sp:7,gp:0,cs:VS]{{Use=All with fewer than 8HD are [blinded](!rounds --target area|@{selected|token_id}|\\amp64;{target|Which creatures are blinded?|token_id}|Blinded|\\amp#91;[2d4]\\amp#93;|-1|Blinded by the prismatic spray|bleeding-eye), apply other effects manually}}{{effects=Causes seven shimmering, multicolored rays of light to flash from his hand in a triangular spray. To determine which ray strikes a creature, roll [1d8](!\\amp#13;\\amp#47;r 1d8) and consult the table on PHB p186.}}{{hide1=It includes all colors of the visible spectrum; each ray has a different power and purpose. Any creature with fewer than 8 Hit Dice struck by a ray is blinded for 2d4 rounds, regardless of any other effect.\nAny creature in the area of effect will be touched by one or more of the rays. To determine which ray strikes a creature, roll 1d8 and consult the following table:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;[d8 roll](!\\amp#13;\\amp#47;r 1d8)\\amplt;/th;\\ampgt;\\amplt;th\\ampgt;Color of Ray\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Order of Ray\\amplt;/th;\\ampgt;\\amplt;th;\\ampgt;Effect of Ray\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;1\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Red\\amplt;/td\\ampgt;\\amplt;td\\ampgt;1st\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Inflicts 20 points of damage, save vs. spell for half.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;2\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Orange\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2nd\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Inflicts 40 points of damage, save vs. spell for half.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;3\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Yellow\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3rd\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Inflicts 80 points of damage, save vs. spell for half.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;4\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Green\\amplt;/td\\ampgt;\\amplt;td\\ampgt;4th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Save vs. poison or die; survivors suffer 20 points of poison damage.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;5\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Blue\\amplt;/td\\ampgt;\\amplt;td\\ampgt;5th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Save vs. petrification or be turned to stone.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;6\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Indigo\\amplt;/td\\ampgt;\\amplt;td\\ampgt;6th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Save vs. wand or go insane.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;7\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Violet\\amplt;/td\\ampgt;\\amplt;td\\ampgt;7th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Save vs. spell or be sent to another plane.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;8\\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt; \\amplt;/td\\ampgt;\\amplt;td\\ampgt;Struck by 2 rays, roll again twice (ignore 8s)\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;}}'},
- {name:'Reverse-Gravity',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nReverse Gravity\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Reverse Gravity,MUspellL7,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[5*@{selected|mu-casting-level}]] yards}}{{duration=[@{selected|mu-casting-level} rounds](!rounds --target-nosave caster|@{selected|token_id}|Reverse-gravity|@{selected|mu-casting-level}|-1|Gravity is reversed in the area of effect. How uplifting!|fluffy-wing)}}{{aoe=[30ft x 30ft.](!rounds --aoe @{selected|token_id}|square|yards|[[5*@{selected|mu-casting-level}]]|10||magic)}}{{save=None}}{{Use=Use the *duration* button to set a status timer for the spell}}{{reference=PHB p186}}SpellData=[w:Reverse Gravity,lv:7,sp:7,gp:0.1,cs:VSM]{{effects=Reverses gravity in the area of effect, causing all unattached objects and creatures within it to "fall" upward.}}{{hide1=The reverse gravity lasts as long as the caster desires or until the spell expires. If some solid object is encountered in this "fall," the object strikes it in the same manner as it would during a normal downward fall. At the end of the spell duration, the affected objects and creatures fall downward. As the spell affects an area, objects tens, hundreds, or even thousands of feet in the air above the area can be affected.}}{{materials=A loadstone and iron filings, at a total cost of 1sp}}'},
- {name:'Sequester',type:'muspelll7',ct:'7',charge:'uncharged',cost:'10',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nSequester\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Illusion/Phantasm, Abjuration}}Specs=[Sequester,MUspellL7,1H,Illusion/Phantasm|Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=[[7+@{selected|mu-casting-level}]] days}}{{aoe=[@{selected|mu-casting-level} x 2ft. cubes](!rounds --aoe @{selected|token_id}|bolt|feet|0|||magic)}}{{save=Special}}{{reference=PHB p186}}SpellData=[w:Sequester,lv:7,sp:7,gp:10,cs:VSM]{{effects=Not only prevents detection and location spells from working to detect or locate the objects affected by the sequester spell, it also renders the affected object(s) invisible to any form of sight or seeing.}}{{hide1=Thus, a *sequester* spell can mask a secret door, a treasure vault, etc. Of course, the spell does not prevent the subject from being discovered through tactile means or through the use of devices (such as a robe of eyes or a gem of seeing). If cast upon a creature who is unwilling to be affected, the creature receives a normal saving throw. Living creatures (and even undead types) affected by a sequester spell become comatose and are effectively in a state of suspended animation until the spell wears off or is dispelled.}}{{materials=A basilisk eyelash (difficult to source), gum arabic, and a dram of whitewash. Total cost 10gp}}'},
- {name:'Shadow-Walk',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nShadow Walk\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Illusion, Enchantment}}Specs=[Shadow Walk,MUspellL7,1H,Illusion|Enchantment]{{components=V,S}}{{time=[[1]]}}{{range=Touch}}{{duration=[[6*@{selected|mu-casting-level}]] turns}}{{aoe=Touched Creatures at time of casting}}{{save=Special}}{{reference=PHB p186}}{{Use=Click [touched creature](!rounds --target-save area|@{selected|token_id}|\\amp#64;{target|Who is touching you?|token_id}|Shadow-walk|[[60*@{selected|mu-casting-level}]]|-1|Walking on the edge between the Prime Material plane \\amp the Demiplane of Shadow|half-haze) then target each creature in turn (start with the caster). The GM will need to confirm selections, making or asking for saving throws where required}}SpellData=[w:Shadow Walk,lv:7,sp:7,gp:0,cs:VS]{{effects=Must be in an area of heavy shadows. The caster and any creature he touches are then transported to the edge of the Prime Material Plane where it borders the Demiplane of Shadow and can move at a rate of up to 7 miles per turn, moving normally on the borders of the Demiplane of Shadow but much more rapidly relative to the Prime Material Plane. The wizard knows where he will come out on the Prime Material Plane.}}{{hide1=The *shadow walk* spell can also be used to travel to other planes that border on the Demiplane of Shadow, but this requires the potentially perilous transit of the Demiplane of Shadow to arrive at a border with another plane of reality.\nAny creatures touched by the wizard when *shadow walk* is cast also make the transition to the borders of the Demiplane of Shadow. They may opt to follow the wizard, wander off through the plane, or stumble back into the Prime Material Plane (50% chance for either result if they are lost or abandoned by the wizard). Creatures unwilling to accompany the wizard into the Demiplane of Shadow receive a saving throw, negating the effect if successful.}}'},
- {name:'Simulacrum',type:'muspelll7',ct:'7',charge:'uncharged',cost:'1000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nSimulacrum\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Illusion-Phantasm}}Specs=[Shadow Walk,MUspellL7,1H,Illusion-Phantasm]{{components=V,S,M}}{{time=Special}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p186}}{{Use=If the creature is in the *Drag \\amp Drop* creature library, GM can *Drag \\amp Drop* one and alter the HP via the dropped token}}SpellData=[w:Simulacrum,lv:7,sp:7,gp:1000,cs:VSM]{{effects=Create what appears as a duplicate of any creature, but with only 51% to 60% (50% + 1d10%) of the hit points of the real creature, there are personality differences, there are areas of knowledge that the duplicate does not have, and a *detect magic* spell will instantly reveal it as a simulacrum, as will a *true seeing* spell.}}{{hide1=At all times the simulacrum remains under the absolute command of the wizard who created it. No special telepathic link exists, so command must be exercised in some other manner. The spell creates the form of the creature, but it is only a zombielike creation. A *reincarnation* spell must be used to give the duplicate a vital force, and a *limited wish* spell must be used to empower the duplicate with 40% to 65% (35% + 5 to 30%) of the knowledge and personality of the original. The level of the simulacrum, if any, is from 20% to 50% of that of the original creature.\nThe duplicate creature is formed from ice or snow. The spell is cast over the rough form and some piece of the creature to be duplicated must be placed inside the snow or ice. Additionally, the spell requires powdered ruby.\nThe simulacrum has no ability to become more powerful; it cannot increase its level or abilities. If destroyed, it reverts to snow and melts into nothingness. Damage to the simulacrum can be repaired by a complex process requiring at least one day, 100 gp per hit point, and a fully equipped laboratory.}}{{materials=Powdered Ruby worth 1,000gp}}'},
- {name:'Spell-Turning',type:'muspelll7',ct:'7',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nSpell Turning\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Abjuration}}Specs=[Spell Turning,MUspellL7,1H,Abjuration]{{components=V,S,M}}{{time=[[7]]}}{{range=[[0]]}}{{duration=Up to [[[3*@{selected|mu-casting-level}]] rounds](!rounds --target-nosave caster|@{selected|token_id}|Spell-turning|[[3*@{selected|mu-casting-level}]]|-1|Those spells tend to just bounce off you|aura)}}{{aoe=The caster}}{{save=None}}{{reference=PHB p187}}{{Use=Use the *duration* button to set a status timer on the caster. Targetable spells should be re-targeted on the reflected target. Spells with effects placed on the caster will need to be *rejected* by the GM or the *Maint Menu* used to remove the effect. Some reflected spells may need to be dealt with manually}}SpellData=[w:Spell Turning,lv:7,sp:7,gp:1,cs:VSM]{{effects=Causes spells cast against the wizard to rebound on the original caster.}}{{hide1=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.\nFrom seven to ten spell levels are affected by the turning. The exact number is secretly rolled by the DM; the player never knows for certain how effective the spell is.\nA spell may be only partially turned--divide the number of remaining levels that can be turned by the spell level of the incoming spell to see what fraction of the effect is turned, with the remainder affecting the caster. For example, an incoming fireball is centered on a wizard with one level of spell turning left. This means that 2/3 of the fireball affects the protected wizard, 1/3 affects the caster, and each is the center of a fireball effect. If the rolled damage is 40 points, the protected wizard receives 27 points of damage and the caster suffers 13. Both (and any creatures in the respective areas) can roll saving throws vs. spell for half damage. A partially turned hold or paralysis spell will act as a slow spell on those who are 50% or more affected.\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\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;[D100 Roll](!\\amp#13;\\amp#47;gr 1d100)\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Effect\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;01-70\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Spell drains away without effect\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;71-80\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Spell affects both equally at full damage\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;81-97\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Both turning effects are rendered nonfunctional for 1d4 turns\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;98-00\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Both casters go through a rift into the Positive Energy plane\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;}}{{materials=A small silver mirror worth 20gp that can be reused 20 times}}'},
- {name:'Statue',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0.03',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nStatue\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Statue,MUspellL7,1H,Alteration]{{components=V,S,M}}{{time=[[7]]}}{{range=Touch}}{{duration=[[@{selected|mu-casting-level}]] hours}}{{aoe=[Creature touched](!rounds --target-save single|@{selected|token_id}|\\amp#64;{target|Who wants a statue of themselves?|token_id}|Statue|[[60*@{selected|mu-casting-level}]]|-1|Wow - you can stand really still!|white-tower)}}{{save=Special}}{{reference=PHB p187}}SpellData=[w:Statue,lv:7,sp:7,gp:0.03,cs:VSM]{{effects=The wizard or other creature is apparently turned to solid stone, along with any garments and equipment worn or carried.}}{{hide1=The initial transformation from flesh to stone requires one full round after the spell is cast.\nDuring the transformation, there\'s an 18% chance that the targeted creature suffers a system shock failure and dies. The creature must roll percentile dice and add its Constitution score to the roll. If the total is 18 or less, the creature dies. If the total is 19 or more, the creature survives the transformation; the creature can withstand any inspection and appear to be a stone statue, although faint magic is detected from the stone if someone checks for it. Note that a creature with a Constitution of 18 or more will always survive the transformation.\nDespite being in this condition, the petrified individual can see, hear, and smell normally. Feeling is limited to those sensations that can affect the granite-hard substance of the individual\'s body--i.e., chipping is equal to a slight wound, but breaking off one of the statue\'s arms is serious damage.\nThe individual under the magic of a statue spell can return to his normal state instantly, act, and then return to the statue state, if he so desires, as long as the spell duration is in effect.}}{{materials=Lime, sand, and a drop of water stirred by an iron bar, such as a nail or spike (total cost 3cp)}}'},
- {name:'Steal-Enchantment',type:'muspelll7',ct:'600',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nSteal Enchantment\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Enchantment}}Specs=[Steal Enchantment,MUspellL7,1H,Enchantment]{{components=V,S,M}}{{time=[[1]] Hour}}{{range=Touch}}{{duration=Permanent}}{{aoe=[[1]] Item}}{{save=Negates}}{{reference=The Complete Wizard\'s Handbook}}SpellData=[w:Steal-Enchantment,lv:7,sp:600,gp:0,cs:VSM]{{effects="Steals" the enchantment from a magical item and places it within another, non-magical item (the material component).}}{{hide1=Both objects must be touched by the wizard during casting. The two items must be of the same category (blunt weapon, edged weapon, ring, amulet, shield, armor, wand, etc.).\nThe enchantment can be transferred only to a nonmagical item. Only the energy of one item can be transferred; it is not possible to combine two magical items into one item. The new item has all the properties of the original magical item (including the same number of charges, if any).\nAt the culmination of the spell, the original magical object is allowed an item saving throw vs. disintegration with all modifiers it is allowed as a magical item. Exceptionally powerful objects (such as artifacts) may be considered to automatically succeed the saving throw at the DM\'s discretion.\nIf the saving throw is successful, the magical object resists the effect and the spell ends in failure. If the roll is failed, the magical item loses all of its powers, which are transferred to the previously nonmagical object.\nEven if the magical item fails its saving throw, the spell\'s success is not guaranteed. There is a chance that the enchantment might be lost. The base chance of this occurring is 100%, modified by -5% per level of the caster. Thus, a 20th-level wizard has no chance of losing the magic. If the enchantment is lost, both items become nonmagical.}}{{materials=The nonmagical item which is to receive the enchantment. It must be of equal or greater value than the object to be drained. Paid for when bought}}'},
- {name:'Teleport-Without-Error',type:'muspelll7',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nTeleport Without Error\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Teleport Without Error,MUspellL7,0H,Alteration]{{components=V}}{{time=[[1]]}}{{range=Touch}}{{duration=Instantaneous}}{{aoe=Special}}{{save=None}}{{reference=PHB p187}}SpellData=[w:Teleport Without Error,lv:7,sp:1,gp:0,cs:V]{{effects=Transport the caster, along with the material weight noted for a *teleport* spell (see PHB p172), to any known location in his home plane with no chance for error.}}{{hide1=The spell also enables the caster to travel to other planes of existence, but any such plane is, at best, "studied carefully." This assumes that the caster has, in fact, actually been to the plane and carefully perused an area for an eventual teleportation without error spell. The table for the teleport spell is used, with the caster\'s knowledge of the area to which transportation is desired used to determine the chance of error. (For an exception, see the 9th-level wizard spell succor.) The caster can do nothing else in the round that he appears from a teleport.}}'},
- {name:'Vanish',type:'muspelll7',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nVanish\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Alteration}}Specs=[Vanish,MUspellL7,0H,Alteration]{{components=V}}{{time=[[2]]}}{{range=Touch}}{{duration=Special}}{{aoe=1 object}}{{save=None}}{{reference=PHB p187}}SpellData=[w:Vanish,lv:7,sp:2,gp:0,cs:V]{{effects=Causes an object to vanish (i.e., to be teleported as if by a teleport spell) if it weighs no more than [[50*@{selected|mu-casting-level}]] pounds. The maximum volume of material that can be affected is [[3*@{selected|mu-casting-level}]] cu.ft. An object that exceeds either limitation is unaffected and the spell fails.}}{{hide1=If desired, a vanished object can be placed deep within the Ethereal Plane. In this case, the point from which the object vanished remains faintly magical until the item is retrieved. A successful dispel magic spell cast on the point will bring the vanished item back from the Ethereal Plane. Note that creatures and magical forces cannot be made to vanish.\nThere is a 1% chance that a vanished item will be disintegrated instead. There is also a 1% chance that a creature from the Ethereal Plane is able to gain access to the Prime Material Plane through the vanished item\'s connection.}}'},
- {name:'Vision',type:'muspelll7',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nVision\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 7 Wizard}}{{school=Divination}}Specs=[Vision,MUspellL7,0H,Divination]{{components=V,S,M}}{{time=[[7]]}}{{range=[[0]]}}{{duration=Special}}{{aoe=The caster}}{{save=None}}{{reference=PHB p187}}SpellData=[w:Vision,lv:7,sp:7,gp:0,cs:VSM]{{effects=Calls upon whatever power the caster desires aid from and can ask a question that will be answered with a vision.}}{{materials=The sacrifice of something valued by the spellcaster or by the power supplicated. The more precious the sacrifice, the better the chance of spell success. A very precious item grants a bonus of +1 to the dice roll, an extremely precious item adds +2, and a priceless item adds +3. DM will adjudicate the cost, which must be deducted from the character}}{{hide1=Two six-sided dice are rolled. If they total 2 to 6, the power is annoyed and refuses to answer the question; instead, the power causes the wizard to perform some service (by an ultrapowerful geas or quest). If the dice total 7 to 9, the power is indifferent and gives some minor vision, though it may be unrelated to the question. If the dice total 10 or better, the power grants the vision.\nThe material component of the spell is the sacrifice of something valued by the spellcaster or by the power supplicated. The more precious the sacrifice, the better the chance of spell success. A very precious item grants a bonus of +1 to the dice roll, an extremely precious item adds +2, and a priceless item adds +3.}}'},
+ db:[{name:'Antipathy-Sympathy',type:'muspelll8',ct:'600',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\n**Antipathy-Sympathy**\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Enchantment-Charm}}Specs=[Antipathy-Sympathy,MUspellL8,1H,Enchantment-Charm]{{components=V,S,M}}{{time=[[1]] hour}}{{range=[[30]] yards}}{{duration=[[2*@{selected|mu-casting-level}]] hours}}{{aoe=[10ft. cube](!rounds --aoe @{selected|token_id}|square|feet|[[120*@{selected|mu-casting-level}]]|10||magic) or one item}}{{save=Special}}{{reference=PHB p188}}{{Use=Select [Antipathy](!rounds --target-nosave caster|@{selected|token_id}|Antipathy|[[120*@{selected|mu-casting-level}]]|-1|Area of Antipathy is currently active|screaming) or [Sympathy](!rounds --target-nosave caster|@{selected|token_id}|Sympathy|[[120*@{selected|mu-casting-level}]]|-1|Area of Sympathy is currently active|grab) to set duration status timer on the caster token}}SpellData=[w:Antipathy-Sympathy,lv:8,sp:600,gp:0,cs:VSM]{{effects=This spell allows the wizard to set certain vibrations to emanate from an object or location that tend to either repel or attract a specific type of intelligent creature or characters of a particular alignment. The wizard must decide which effect is desired with regard to what creature type or alignment before beginning the spellcasting, for the components of each application differ. The spell cannot be cast upon living creatures.}}{{hide1=[Antipathy](!rounds --target caster|@{selected|token_id}|Antipathy|[[120*@{selected|mu-casting-level}]]|-1|Area of Antipathy is currently active|screaming): This spell causes the affected creature or alignment type to feel an overpowering urge to leave the area or to not touch the affected item. If a saving throw vs. spell is successful, the creature can stay in the area or touch the item, but the creature will feel very uncomfortable, and a persistent itching will cause it to suffer the loss of 1 point of Dexterity per round (for the spell\'s duration), subject to a maximum loss of 4 points and a minimum Dexterity of 3. Failure to save vs. spell forces the being to abandon the area or item, shunning it permanently and never willingly returning to it until the spell is removed or expires.\nThe material component for this application of the spell is a lump of alum soaked in vinegar.\n[Sympathy](!rounds --target caster|@{selected|token_id}|Sympathy|[[120*@{selected|mu-casting-level}]]|-1|Area of Sympathy is currently active|grab): By casting the sympathy application of the spell, the wizard can cause a particular type of creature or alignment of character to feel elated and pleased to be in an area or touching or possessing an object or item. The desire to stay in the area or touch the object is overpowering. Unless a saving throw vs. spell is successfully rolled, the creature or character will stay or refuse to release the object. If the saving throw is successful, the creature or character is released from the enchantment, but a subsequent saving throw must be made 1d6 turns later. If this saving throw fails, the affected creature will return to the area or object.\nThe material components of this spell are 1,000 gp worth of crushed pearls and a drop of honey.\nNote that the particular type of creature to be affected must be named specifically - for example, red dragons, hill giants, wererats, lammasu, catoblepas, vampires, etc. Likewise, the specific alignment must be named - for example, chaotic evil, chaotic good, lawful neutral, true neutral, etc.\nIf this spell is cast upon an area, a 10-foot cube can be enchanted for each experience level of the caster. If an object or item is enchanted, only that single thing can be enchanted; affected creatures or characters save vs. spell with a -2 penalty.}}{{materials=\n*Antipathy*: a lump of alum soaked in vinegar.\n*Sympathy*: 1,000 gp worth of crushed pearls and a drop of honey}}'},
+ {name:'Bigbys-Clenched-Fist',type:'magic|muspelll8',ct:'600',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nBigby\'s Clenched Fist\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Evocation}}Specs=[Bigbys Clenched Fist,Magic|MUspellL8,1H|2H,Evocation],[Bigbys Clenched Fist,Magic|MUspellL8,1H|2H,Evocation],[Bigbys Clenched Fist,Magic|MUspellL8,1H|2H,Evocation],[Bigbys Clenched Fist,Magic|MUspellL8,1H|2H,Evocation],[Bigbys Clenched Fist,Magic|MUspellL8,1H|2H,Evocation]{{components=V,S,M}}ToHitData=[w:Fist Roll d20,cmd:!\\amp#13;\\amp#47;r 1d20],[w:Fist 1-12,cmd:!\\amp#13;\\amp#47;r 1d6],[w:Fist 13-16,cmd:!\\amp#13;\\amp#47;r 2d6],[w:Fist 17-19,cmd:!rounds --target single|\\amp#64;{selected|token_id}|\\amp#64;{target|Who did you punch?|token_id}|stunned|1|-1|Stunned for 1 round|back-pain\\amp#13;\\amp#47;r 3d6],[w:Fist 20,cmd:!rounds --target single|\\amp#64;{selected|token_id}|\\amp#64;{target|Who did you punch?|token_id}|stunned|3|-1|Stunned for 3 rounds|back-pain\\amp#13;\\amp#47;r 4d6]{{time=[[8]]}}{{range=[[[5*@{selected|mu-casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[10*@{selected|mu-casting-level}]]||magic|true)}}{{duration=[[@{selected|mu-casting-level}]] rounds}}{{aoe=Special}}{{save=None}}{{reference=PHB p188}}SpellData=[w:Bigbys Clenched Fist,lv:8,sp:600,gp:1,cs:VSM,on:!rounds --target caster|@{selected|token_id}|bigbys-fist|@{selected|mu-casting-level}|-1|Wielding Bigby\'s Clenched Fist|fist,off:!rounds --removetargetstatus @{selected|token_id}|bigbys-fist|silent]{{Use=After casting this spell, use the *Change Weapon* dialog (which should be automatically displayed) to take *Bigby\'s Clenched Fist* in-hand as a weapon, and then attack with it each round until it expires}}{{effects=Brings forth a huge, disembodied hand that is balled into a fist. Spellcaster can cause it to strike one opponent each round, which always hits and with the following effects:\n\\amplt;table\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;D20 Roll\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Result\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\n\\amplt;tr\\ampgt;\\amplt;td\\ampgt;1-12\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Glancing blow - 1d6\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;13-16\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Solid punch - 2d6\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;17-19\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Hard punch - 3d6 \\amp stunned for 1 round\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;20\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Crushing blow\\amp#42; - 4d6 \\amp stunned for 3 rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\n\\amp#42;The wizard adds +4 to the die rolls of subsequent attacks if the opponent is stunned, as the opponent is not capable of dodging or defending against the attack effectively.\nThe fist has AC 0, and [[@{selected|hp|max}]]HP}}{{materials=A leather glove and a small device (similar to brass knuckles) consisting of four rings joined so as to form a slightly curved line, with an "I" upon which the bottoms of the rings rest. The device must be fashioned of an alloy of copper and zinc: total cost 20gp to procure, but can be used up to 20 times}}'},
+ {name:'Binding',type:'muspelll8',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nBinding\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Enchantment, Evocation}}Specs=[Binding,MUspellL8,1H,Enchantment|Evocation]{{components=V,S,M}}{{time=Special}}{{range=[[[10]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|20|0|magic|true)}}{{duration=Special}}{{aoe=1 creature}}{{save=Special}}{{reference=PHB p188}}SpellData=[w:Binding,lv:8,sp:100,gp:0,cs:VSM]{{effects=Creates a magical restraint to hold a creature, usually from another plane of existence.}}{{hide1=Extraplanar creatures must be confined by a circular diagram; other creatures can be physically confined. The duration of the spell depends upon the form of the binding and the level of the caster(s), as well as the length of time the spell is actually uttered. The components vary according to the form of the spell, but they include a continuous chanting utterance read from the scroll or book page giving the spell; gestures appropriate to the form of binding; and materials such as miniature chains of special metal (silver for lycanthropes, etc.), soporific herbs of the rarest sort, a corundum or diamond gem of great size (1,000 gp value per Hit Die of the subject creature), and a vellum depiction or carved statuette of the subject to be captured.\nMagic resistance applies unless the subject\'s true name is used. A saving throw is not applicable as long as the experience level of the caster is at least twice as great as the Hit Dice of the subject. The caster\'s level can be augmented by one-third of the levels of each assisting wizard of 9th level or higher, and by one level for each assistant of 4th through 8th level. No more than six other wizards can assist with this spell. If the caster\'s level is less than twice the Hit Dice of the subject, the subject gains a saving throw vs. spell, modified by the form of binding being attempted. The various forms of binding are:\n***Chaining:*** The subject is confined by restraints that generate an antipathy spell affecting all creatures who approach the subject, except the caster. Duration is as long as one year per level of the caster(s). The subject of this form of binding (as well as in the slumber and bound slumber versions) remains within the restraining barrier.\n***Slumber:*** Brings a comatose sleep upon the subject for a duration of up to one year per level of the caster(s).\n***Bound Slumber:*** A combination of chaining and slumber that lasts for up to one month per level of the caster(s).\n***Hedged Prison:*** The subject is transported to or otherwise brought within a confined area from which it cannot wander by any means until freed. The spell remains until the\nmagical hedge is somehow broken.\n***Metamorphosis:*** Causes the subject to change to some noncorporeal form, save for its head or face. The binding is permanent until some prescribed act frees the subject.\n***Minimus Containment:*** The subject is shrunken to a height of 1 inch or even less and held within the hedged prison of some gem or similar object. The subject of a minimus containment, metamorphosis, or hedged prison radiates a very faint aura of magic.\nThe subject of the *chaining* form of the spell receives a saving throw with no modifications. However, *slumber* allows the subject a +1 bonus, *bound slumber* a +2 bonus, *hedged prison* a +3 bonus, *metamorphosis* a +4 bonus, and *minimus containment* a +5 bonus to the saving throw. If the subject is magically weakened, the DM can assign a -1, -2, or even -4 penalty to the saving throw. A successful saving throw enables the subject to burst its bonds and do as it pleases.\nA binding spell can be renewed in the case of the first three forms of the spell, for the subject does not have the opportunity to break the bonds. (If anything has caused a weakening of a chaining or slumber version, such as attempts to contact the subject or magically touch it, a normal saving throw applies to the renewal of the spell.) Otherwise, after one year, and each year thereafter, the subject gains a normal saving throw vs. the spell. Whenever it is successful, the binding spell is broken and the creature is free.}}{{materials=Various materials are required for various forms. DM to determine cost. See PHB p188}}'},
+ {name:'Clone',type:'muspelll8',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nClone\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Necromancy}}Specs=[Clone,MUspellL8,1H,Necromancy]{{components=V,S,M}}{{time=[[1]] turn}}{{range=Touch}}{{duration=Permanent}}{{aoe=1 clone}}{{save=None}}{{reference=PHB p189}}{{Use=Drag a copy token on to the playing surface from the journal, then the GM should make the token a "mob" token by deleting the token bar links to the character (leave the token itself linked to the character sheet)}}SpellData=[w:Clone,lv:8,sp:100,gp:0,cs:VSM]{{effects=Creates a duplicate of a human, demihuman, or humanoid creature.}}{{hide1=This clone is in most respects the duplicate of the individual, complete to the level of experience, memories, etc. However, the duplicate really is the person, so if the original and a duplicate exist at the same time, each knows of the other\'s existence; the original erson and the clone will each desire to do away with the other, for such an alter-ego is unbearable to both. If one cannot destroy the other, one will go insane and destroy itself (90% likely to be the clone), or possibly both will become mad and destroy themselves (2% chance). These events nearly always occur within one week of the dual existence.\nNote that the clone is the person as he existed at the time at which the flesh was taken for the spell component, and all subsequent knowledge, experience, etc., is totally unknown to the clone. The clone is a physical duplicate, and possessions of the original are another matter entirely. A clone takes 2d4 months to grow, and only after that time is dual existence established. Furthermore, the clone has one less Constitution point than the body it was cloned from; the cloning fails if the clone would have a Constitution of 0.\nThe DM may, in addition, add other stipulations to the success of a cloning effort, requiring that some trace of life must remain in the flesh sample, that some means of storing and preserving the sample must be devised and maintained, etc.}}{{materials=A small piece of the flesh from the person to be duplicated. The DM may add other stipulations to the success of a cloning effort, e.g. some trace of life must remain in the flesh sample, some means of storing and preserving the sample, etc}}'},
+ {name:'Demand',type:'muspelll8',ct:'100',charge:'uncharged',cost:'1',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nDemand\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Evocation, Enchantment-Charm}}Specs=[Demand,MUspellL8,1H,Evocation|Enchantment-Charm]{{components=V,S,M}}{{time=[[1]] turn}}{{range=Unlimited}}{{duration=Special}}{{aoe=1 creature}}{{save=Special}}{{reference=PHB p189}}SpellData=[w:Demand,lv:8,sp:100,gp:1,cs:VSM]{{effects=Allows a brief contact with a far distant creature. The message can also contain a *suggestion*}}{{hide1=This spell is very much like the 5th-level wizard spell sending, allowing a brief contact with a far distant creature. However, with this spell the message can also contain a [*suggestion*](!magic --display-ability @{selected|token_id}|MU-Spells-DB|Suggestion) (see the 3rd-level wizard spell suggestion), which the subject will do its best to carry out if it fails its saving throw vs. spell, made with a -2 penalty. Of course, if the message is impossible or meaningless according to the circumstances that exist for the subject at the time the demand comes, the message is understood but no saving throw is necessary and the suggestion is ineffective.\nThe caster must be familiar with the creature contacted and must know its name and appearance well. If the creature in question is not in the same plane of existence as the spellcaster, there is a base 5% chance that the demand does not arrive. Local conditions on other planes may worsen this chance considerably at the option of the DM. The demand, if received, will be understood even if the creature has an Intelligence ability score as low as 1 (animal Intelligence). Creatures of demigod status or higher can choose to come or not, as they please.\nThe demand message to the creature must be 25 words or less, including the suggestion. The creature can also give a short reply immediately.}}{{materials=A pair of cylinders, each open at one end, connected by a thin piece of copper wire costing 20gp to procure, reusable 20 times, and some small part of the subject creature--a hair, a bit of nail, etc}}'},
+ {name:'Glassteel',type:'muspelll8',ct:'8',charge:'uncharged',cost:'0.5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nGlassteel\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Alteration}}Specs=[Glasteel,MUspellL8,1H,Alteration]{{components=V,S,M}}{{time=[[8]]}}{{range=Touch}}{{duration=Permanent}}{{aoe=[Object touched](!rounds --aoe @{selected|token_id}||feet|0)}}{{save=None}}{{reference=PHB p189}}SpellData=[w:Glassteel,lv:8,sp:8,gp:0.5,cs:VSM]{{effects=Turns normal, nonmagical crystal or glass into a transparent substance that has the tensile strength and unbreakability of actual steel. Only a relatively small volume of material can be affected (a maximum weight of [[10*@{selected|mu-casting-level}]] pounds), and it must form one whole object. AC of the substance is 1}}{{materials=A small piece of glass and a small piece of steel, total cost 5sp}}'},
+ {name:'Incendiary-Cloud',type:'muspelll8',ct:'2',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nIncendiary Cloud\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Alteration, Evocation}}Specs=[Incendiary Cloud,MUspellL8,1H,Alteration|Evocation]{{components=V,S,M}}{{time=[[2]]}}{{range=[[30]] yards}}{{duration=1d6+4 rounds}}{{aoe=[Special](!rounds --aoe @{selected|token_id}||feet|90|||fire --target-nosave caster|@{selected|token_id}|Incendiary-cloud|\\amp#91;[4+1d6]\\amp#93;|-1|An incendiary cloud forms|rolling-bomb)}}{{save=Halves}}{{reference=PHB p189}}{{Use=Select the *area of effect* and a status round counter will be set on the caster. Damage buttons will appear for the caster each round}}SpellData=[w:Incendiary Cloud,lv:8,sp:2,gp:0,cs:VSM]{{effects=Minimum dimensions are a cloud 10 feet tall, 20 feet wide, and 20 feet long. This dense vapor cloud billows forth, and 3rd round begins to flame, for @{selected|mu-casting-level}d2 HP. 4th round @{selected|mu-casting-level}d4 HP, and 5th round @{selected|mu-casting-level}d2 HP as its flames burn out, and in successive rounds is simply harmless smoke that obscures vision within its confines. Creatures within the cloud need to make only one saving throw if it is successful, but if they fail the first saving throw, they roll again on the fourth and fifth rounds (if necessary) to attempt to reduce the damage sustained by one-half.}}{{materials=An available fire source (just as with a pyrotechnics spell), scrapings from beneath a dung pile, and a pinch of dust (no cost)}}'},
+ {name:'Mass-Charm',type:'muspelll8',ct:'8',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nMass Charm\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Enchantment-Charm}}Specs=[Mass Charm,MUspellL8,0H,Enchantment-Charm]{{components=V}}{{time=[[8]]}}{{range=[[5*@{selected|mu-casting-level}]] yards}}{{duration=Special}}{{aoe=[30ft cube](!rounds --aoe @{selected|token_id}|square|feet|[[15*@{selected|mu-casting-level}]]|30||magic)}}{{save=Negates}}{{reference=PHB p190}}{{Use=[Charm Them](!rounds --target multi|@{selected|token_id}|Mass-Charm|99|0|Wow, @{selected|character_name} is so great! There\'s something about them...|chained-heart|svspe\\clon;-2)}}SpellData=[w:Mass Charm,lv:8,sp:8,gp:0,cs:V]{{effects=Affects large numbers of either persons or monsters just as a *charm person* or *charm monster* spell.}}{{hide1=The mass charm spell, however, affects a number of creatures whose combined levels of experience or Hit Dice does not exceed twice the level of experience of the spellcaster. All affected creatures must be within the spell range and within a 30-foot cube. Note that the creatures\' saving throws are unaffected by the number of recipients (see the *charm person* and *charm monster* spells), but all target creatures are subject to a penalty of -2 on their saving throws because of the efficiency and power of this spell. The Wisdom bonus against charm spells does apply.}}'},
+ {name:'Maze',type:'muspelll8',ct:'3',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nMaze\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration-Summoning}}Specs=[Maze,MUspellL8,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[3]]}}{{range=[[[5*@{selected|mu-casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[10*@{selected|mu-casting-level}]]||magic|true)}}{{duration=[Special](!rounds --target single|@{selected|token_id}|\\amp#64;{target|Who do you want to a-Maze?|token_id}|Maze|\\amp#91;[\\amp#63;{What intelligence is target creature?|under 3,2d4|3-5,1d4|6-8,5d4|9-11,4d4|12-14,3d4|15-17,2d4|18+,1d4}]\\amp#93;|-1|You are in a labyrinth of endless corridors... You are in a labyrinth of tiny, twisting corridors... You are in...|screaming)}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p190}}SpellData=[w:Maze,lv:8,sp:3,gp:0,cs:VS]{{effects=An extradimensional space is brought into being. The subject vanishes into the shifting labyrinth of force planes for a period of time that is dependent upon its Intelligence.}}{{hide1=(Note: Minotaurs are not affected by this spell.)\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;Intelligence of Mazed Creature\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Time Trapped in Maze\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;under 3\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[2d4](!\\amp#13;\\amp#47;r 2d4) turns\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;3-5\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[1d4](!\\amp#13;\\amp#47;r 1d4) turns\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;6-8\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[5d4](!\\amp#13;\\amp#47;r 5d4) rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;9-11\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[4d4](!\\amp#13;\\amp#47;r 4d4) rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;12-14\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[3d4](!\\amp#13;\\amp#47;r 3d4) rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;15-17\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[2d4](!\\amp#13;\\amp#47;r 2d4) rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;18+\\amplt;/td\\ampgt;\\amplt;td\\ampgt;[1d4](!\\amp#13;\\amp#47;r 1d4) rounds\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nNote that teleport and dimension door spells will not help a character escape a maze spell, although a plane shifting spell will.}}'},
+ {name:'Mind-Blank',type:'muspelll8',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nMind Blank\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Abjuration}}Specs=[Mind Blank,MUspellL8,1H,Abjuration]{{components=V,S}}{{time=[[1]]}}{{range=[30 yards](!rounds --aoe @{selected|token_id}|circle|yards|0|60||magic|true)}}{{duration=[1 day](!rounds --target-nosave single|@{selected|token_id}|\\amp#64;{target|Who\'s mind is blank to others?|token_id}|Mind-blank|99|0|You are protected from all forms of mind reading|white-tower)}}{{aoe=1 creature}}{{save=None}}{{reference=PHB p190}}SpellData=[w:Mind Blank,lv:8,sp:1,gp:0,cs:VS]{{effects=The creature is totally protected from all devices and spells that detect, influence, or read emotions or thoughts.}}{{hide1=This protects against *augury, charm, command, confusion, divination, empathy* (all forms), *ESP, fear, feeblemind, mass suggestion, phantasmal killer, possession, rulership, soul trapping, suggestion,* and *telepathy*. Cloaking protection also extends to the prevention of discovery or information gathering by *crystal balls* or other scrying devices, *clairaudience, clairvoyance, communing, contacting other planes,* or wish-related methods (*wish* or *limited wish*). Of course, exceedingly powerful deities can penetrate the spell\'s barrier.}}'},
+ {name:'Monster-Summoning-VI',type:'muspelll8',ct:'8',charge:'uncharged',cost:'0.1',body:'\\amp{template:'+fields.spellTemplate+'}{{}}Specs=[Monster Summoning VI,MUspellL8,1H,Conjuration-Summoning]{{}}SpellData=[w:Monster Summoning VI,lv:8,sp:8,gp:0.1,cs:VSM]{{}}%{MU-Spells-DB|Monster-Summoning-V}{{title=@{selected|casting-name} casts\nMonster Summoning VI\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration-Summoning}}{{components=V,S,M}}{{time=[[8]]}}{{range=Special}}{{duration=[[7+@{selected|mu-casting-level}]] rounds}}{{aoe=[80yd radius](!rounds --aoe @{selected|token_id}|circle|yards|0|160||magic|true)}}{{save=None}}{{reference=PHB p190}}{{effects=[1d3](!\\amp#13;\\amp#47;r 1d3) 6th level monsters (selected by the DM from the Monster Summoning VI Table in the MC) appear in the area, placed by the caster. Attack to best of their ability until caster demands attack cease, spell expires, or are slain. Disappear when slain, no morale checks. If can communicate and not attacking, caster can ask them to perform tasks.}}{{materials=A tiny bag and a small candle, costing 1sp}}'},
+ {name:'Otilukes-Telekinetic-Sphere',type:'muspelll8',ct:'4',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nOtiluke\'s Telekinetic Sphere\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Evocation, Alteration}}Specs=[Otilukes Telekinetic Sphere,MUspellL8,1H,Evocation|Alteration]{{components=V,S,M}}{{time=[[4]]}}{{range=20 yards}}{{duration=[[2*@{selected|mu-casting-level}]] rounds}}{{aoe=[@{selected|mu-casting-level}ft. diameter sphere](!rounds --aoe @{selected|token_id}|circle|feet|60|@{selected|mu-casting-level}||light)}}{{save=Negates}}{{reference=PHB p190}}SpellData=[w:Otilukes Telekinetic Sphere,lv:8,sp:4,gp:500,cs:VSM]{{effects=Exactly the same as the 4th-level wizard spell Otiluke\'s resilient sphere, with the addition that the creatures or objects inside the globe are nearly weightless--anything contained within it weighs only 1/16 its normal weight.}}{{hide1=Any subject weighing up to 5,000 pounds can be telekinetically lifted in the sphere by the caster. Range of control extends to a maximum distance of 10 yards per level after the sphere has actually succeeded in encapsulating a subject or subjects. Note that even if more than 5,000 pounds of weight is englobed, the perceived weight is only 1/16 of the actual weight, so the orb can be rolled without exceptional effort. Because of the reduced weight, rapid motion or falling within the field of the sphere is relatively harmless to the object therein, although it can be disastrous should the globe disappear when the subject inside is high above a hard surface. The caster can dismiss the effect with a word.}}{{materials=A hemispherical piece of diamond costing 500gp, a matching piece of gum arabic, and a pair of small bar magnets, which are consumed by the spell}}'},
+ {name:'Ottos-Irresistible-Dance',type:'muspelll8',ct:'5',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nOtto\'s Irresistible Dance\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Enchantment-Charm}}Specs=[Ottos Irresistible Dance,MUspellL8,1H,Enchantment-Charm]{{components=V}}{{time=[[5]]}}{{range=[Touch](~selected|To-Hit-Spell)}}!setattr --silent --charid @{selected|character_id} --spell-duration|{{duration=[[1d4+1]] rounds}}!!!{{aoe=Creature Touched}}{{save=None}}{{reference=PHB p190}}SpellData=[w:Ottos Irresistible Dance,lv:8,sp:5,gp:0,cs:V]{{effects=Causes the recipient to begin dancing, complete with feet shuffling and tapping.}}{{hide1=This dance makes it impossible for the victim to do anything other than caper and prance; this cavorting worsens the Armor Class of the creature by -4, makes saving throws impossible except on a roll of 20, and negates any consideration of a shield. Note that the creature must be touched, as if melee combat were taking place and the spellcaster were striking to do damage.}}\n!magic --touch @{selected|token_id}|Ottos-irresistable-dance|\\amp#64;{selected|spell-duration}|-1|Dancing the night away...|trophy'},
+ {name:'Permanency',type:'muspelll8',ct:'20',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nPermanency\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Alteration}}Specs=[Permanency,MUspellL8,1H,Alteration]{{components=V,S}}{{time=[[2]] rounds}}{{range=Special}}{{duration=Permanent}}{{aoe=Special}}{{save=None}}{{reference=PHB p190}}SpellData=[w:Permanency,lv:8,sp:20,gp:0,cs:VS]{{effects=This spell affects the duration of certain other spells, making the duration permanent.}}{{hide1=The personal spells upon which a permanency is known to be effective are as follows:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*comprehend languages*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*protection from evil*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*detect evil*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*protection from normal missiles*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*detect invisibility*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*read magic*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*detect magic*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*tongues*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*infravision*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*unseen servant*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*protection from cantrips*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nThe wizard casts the desired spell and then follows it with the permanency spell. Each permanency spell lowers the wizard\'s Constitution by 1 point. The wizard cannot cast these spells upon other creatures. This application of permanency can be dispelled only by a wizard of greater level than the spellcaster was when he cast the spell.\nIn addition to personal use, the permanency spell can be used to make the following object/creature or area-effect spells permanent:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*enlarge*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*prismatic sphere*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*fear*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*stinking cloud*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*gust of wind*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*wall of fire*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*invisibility*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*wall of force*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*magic mouth*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*web*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nAdditionally, the following spells can be cast upon objects or areas only and rendered permanent:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*alarm*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*wall of fire*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*audible glamer*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*distance distortion*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*dancing lights*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*teleport*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*solid fog*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nThese applications to other spells allow it to be cast simultaneously with any of the latter when no living creature is the target, but the entire spell complex then can be dispelled normally, and thus negated.\nThe permanency spell is also used in the fabrication of magical items (see the 6th-level spell enchant an item). At the DM\'s option, permanency might become unstable or fail after a long period of at least 1,000 years. Unstable effects might operate intermittently or fail altogether.\nThe DM may allow other selected spells to be made permanent. Researching this possible application of a spell costs as much time and money as independently researching the selected spell. If the DM has already determined that the application is not possible, the research automatically fails. Note that the wizard never learns what is possible except by the success or failure of his research.}}'},
+ {name:'Polymorph-Any-Object',type:'muspelll8',ct:'10',charge:'uncharged',cost:'5',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nPolymorph Any Object\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Alteration}}Specs=[Polymorph Any Object,MUspellL8,1H,Alteration]{{components=V,S,M}}{{time=[[1]] round}}{{range=[[[5*@{selected|mu-casting-level}]] yards](!rounds --aoe @{selected|token_id}|circle|yards|0|[[5*@{selected|mu-casting-level}]]||magic)}}{{duration=Variable}}{{aoe=Special}}{{save=Special}}{{reference=PHB p191}}SpellData=[w:Polymorph Any Object,lv:8,sp:10,gp:5,cs:VSM]{{effects=Changes one object or creature into another.}}{{hide1=When used as a *polymorph other* or *stone to flesh* spell, simply treat the spell as a more powerful version, with saving throws made with -4 penalties to the die roll. When it is cast in order to change other objects, the duration of the spell depends on how radical a change is made from the original state to its enchanted state, as well as how different it is in size. The DM determines the changes by using the following guidelines:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Kingdom*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Animal, vegetable, mineral\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Class*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Mammals, bipeds, fungi, metals, etc.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Relationship*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Twig is to tree, sand is to beach, etc.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Size*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Smaller, equal, larger\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Shape*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Comparative resemblance of the original to the polymorphed state\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Intelligence*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Particularly with regard to a change in which the end product is more intelligent\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nA change in *kingdom* makes the spell work for hours (if removed by one kingdom) or turns (if removed by two). Other changes likewise affect spell duration. Thus, changing a lion to an androsphinx would be permanent, but turning a turnip to a purple worm would be a change with a duration measured in hours. Turning a tusk into an elephant would be permanent, but turning a twig into a sword would be a change with a duration of several turns.\nAll polymorphed objects radiate a strong magic, and if a *dispel magic* spell is successfully cast upon them, they return to their natural form. Note that a *stone to flesh* spell or its reverse will affect objects under this spell. As with other polymorph spells, damage sustained in the new form can result in the injury or death of the polymorphed creature.\nFor example, it is possible to polymorph a creature into rock and grind it to dust, causing damage, perhaps even death. If the creature was changed to dust to start with, more creative methods to damage it would be needed; perhaps the wizard could use a *gust of wind* spell to scatter the dust far and wide. In general, damage occurs when the new form is altered through physical force, although the DM will have to adjudicate many of these situations.\nThe system shock roll must be applied to living creatures, as must the restrictions noted regarding the *polymorph other* and *stone to flesh* spells. Also note that a polymorph effect often detracts from an item\'s or creature\'s powers, but does not add new powers, except possibly movement capabilities not present in the old form. Thus, a vorpal sword polymorphed into a dagger would not retain vorpal capability. Likewise, valueless items cannot be made into permanent valuable items.}}'},
+ {name:'Power-Word-Blind',type:'muspelll8',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nPower Word, Blind\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration-Summoning}}Specs=[Power Word Blind,MUspellL8,0H,Conjuration-Summoning]{{components=V}}{{time=[[1]]}}{{range=[[5*@{selected|mu-casting-level}]] yards}}{{duration=[Special](!rounds --target-nosave multi|@{selected|token_id}|Blindness|\\amp#63;{How many Hit Dice?|25 or less,99|26-50,[[10*[[1d4+1]]]]|51-100,[[1d4+1]]}|-1|You are blinded, -4 attk \\amp save|bleeding-eye)}}{{aoe=[15ft radius](!rounds --aoe @{selected|token_id}|circle|yards|[[5*@{selected|mu-casting-level}]]|10||dark)}}{{save=None}}{{reference=PHB p191}}SpellData=[w:Power Word Blind,lv:8,sp:1,gp:0,cs:V]{{effects=One or more creatures within the area of effect become sightless.}}{{hide1=The spellcaster selects one creature as the target center, and the effect spreads outward from the center, affecting creatures with the lowest hit point totals first; the spell can also be focused to affect only an individual creature. The spell affects up to 100 hit points of creatures; creatures who currently have 100 or more hit points are not affected and do not count against the number of creatures affected. The duration of the spell depends upon how many hit points are affected. If 25 or fewer hit points are affected, the blindness is permanent until cured. If 26 to 50 hit points are affected, the blindness lasts for 1d4+1 turns. If 51 to 100 hit points are affected, the spell lasts for 1d4+1 rounds. An individual creature cannot be partially affected. If all of its current hit points are affected, it is blinded; otherwise, it is not. Blindness can be removed by a cure blindness or dispel magic spell.}}'},
+ {name:'Prismatic-Wall',type:'muspelll8',ct:'7',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nPrismatic Wall\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration-Summoning}}Specs=[Prismatic Wall,MUspellL8,1H,Conjuration-Summoning]{{components=V,S}}{{time=[[7]]}}{{range=[[10]] yards}}{{duration=[[@{selected|mu-casting-level}]] turns}}{{aoe=[[2*@{selected|mu-casting-level}]]ft high x [[[4*@{selected|mu-casting-level}]]ft long](!rounds --aoe @{selected|token_id}|wall|feet|30|[[4*@{selected|mu-casting-level}]]|2|magic)}}{{save=Special}}{{damage=[Blind creatures](!rounds --target area|@{selected|token_id}|\\amp#64;{target|Who is too close?|token_id}|Prismatic-Wall-Blind|\\amp#91;[2d4]\\amp#93;|-1|Blinded by the colors, -4 attk \\amp AC|bleeding-eye) with less than 8HD in 20ft}}{{reference=PHB p191}}SpellData=[w:Prismatic Wall,lv:8,sp:7,gp:0,cs:VS]{{effects=Conjure a vertical, opaque wall--a shimmering, multicolored plane of light that protects him from all forms of attack.}}{{hide1=The wall flashes with all colors of the visible spectrum, seven of which have a distinct power and purpose. The wall is immobile, and the spellcaster can pass through the wall without harm. However, any creature with fewer than 8 Hit Dice that is within 20 feet of the wall and does not shield its vision is blinded for 2d4 rounds by the colors.\nEach color in the wall has a special effect. Each color can also be negated by a specific magical effect, but the colors must be negated in the precise order of the spectrum. The accompanying table shows the seven colors of the wall, the order in which they appear, their effects on creatures trying to attack the spellcaster, and the magic needed to negate each color.\nThe wall\'s maximum proportions are 4 feet wide per level of experience of the caster and 2 feet high per level of experience. A prismatic wall spell cast to materialize in a space occupied by a creature is disrupted and the spell is wasted.\n\\amplt;table style="border:1px solid black" width="100%"\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;th colspan="4"\\ampgt;Prismatic Wall Effects\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;th\\ampgt;Color\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Order\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Effect of Color\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Spell Negated By\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Red\\amplt;/td\\ampgt;\\amplt;td\\ampgt;1st\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops nonmagical missiles--inflicts 20 points of damage, save for half\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*cone of cold*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Orange\\amplt;/td\\ampgt;\\amplt;td\\ampgt;2nd\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops magical missiles--inflicts 40 points of damage, save for half\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*gust of wind*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Yellow\\amplt;/td\\ampgt;\\amplt;td\\ampgt;3rd\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops poisons, gases, and petrification--inflicts 80 pointsof damage, save for half \\amplt;/td\\ampgt;\\amplt;td\\ampgt;*disintegrate*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Green\\amplt;/td\\ampgt;\\amplt;td\\ampgt;4th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops breath weapons--save vs. poison or die;\nsurvivors suffer 20 points of damage \\amplt;/td\\ampgt;\\amplt;td\\ampgt;*passwall*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Blue\\amplt;/td\\ampgt;\\amplt;td\\ampgt;5th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops location/detection and mental attacks--save vs.petrification or turn to stone\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*magic missile*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Indigo\\amplt;/td\\ampgt;\\amplt;td\\ampgt;6th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Stops magical spells--save vs. wand or go insane \\amplt;/td\\ampgt;\\amplt;td\\ampgt;*continual light*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr style="border:1px solid black"\\ampgt;\\amplt;td\\ampgt;Violet\\amplt;/td\\ampgt;\\amplt;td\\ampgt;7th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;Force field protection--save vs. spell or be sent to\nanother plane\\amplt;/td\\ampgt;\\amplt;td\\ampgt;*dispel magic*\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;}}'},
+ {name:'Screen',type:'muspelll8',ct:'100',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nScreen\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Divination, Illusion}}Specs=[Screen,MUspellL8,1H,Divination|Illusion]{{components=V,S}}{{time=[[1]] turn}}{{range=[[0]]}}{{duration=[[[@{selected|mu-casting-level}]] hours](!rounds --target-nosave caster|@{selected|token_id}|Screen|[[60*@{selected|mu-casting-level}]]|-1|Maintaining an area screened from scrying eyes|white-tower)}}{{aoe=[[[@{selected|mu-casting-level}]] x 30ft cubes](!rounds --aoe @{selected|token_id}|rectangle|feet|0|||magic)}}{{save=Special}}{{reference=PHB p192}}SpellData=[w:Screen,lv:8,sp:100,gp:0,cs:VS]{{effects=Combines several elements to create a powerful protection from scrying and direct observation.}}{{hide1=When the spell is cast, the wizard dictates what will and will not be observed in the area of effect. The illusion created must be stated in general terms. Thus, the caster could specify the illusion of him and another playing chess for the duration of the spell, but he could not have the illusionary chess players take a break, make dinner, and then resume their game. He could have a crossroads appear quiet and empty even while an army is actually passing through the area. He could specify that no one be seen (including passing strangers), that his troops be undetected, or even that every fifth man or unit should be visible. Once the conditions are set, they cannot be changed.\nAttempts to scry the area automatically detect the image stated by the caster with no saving throw allowed. Sight and sound are appropriate to the illusion created. A band of men standing in a meadow could be concealed as an empty meadow with birds chirping, etc. Direct observation may allow a saving throw (as per a normal illusion), if there is cause to disbelieve what is seen. Certainly onlookers in the area would become suspicious if the column of a marching army disappeared at one point to reappear at another! Even entering the area does not cancel the illusion or necessarily allow a saving throw, assuming the hidden beings take care to stay out of the way of those affected by the illusion.}}'},
+ {name:'Sertens-Spell-Immunity',type:'muspelll8',ct:'10',charge:'uncharged',cost:'500',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nSerten\'s Spell Immunity\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Abjuration}}Specs=[Sertens Spell Immunity,MUspellL8,1H,Abjuration]{{components=V,S,M}}{{time=1 round for each recipient}}{{range=Touch}}!setattr --silent --charid @{selected|character_id} --spell-duration|{{duration=[[floor(10*@{selected|mu-casting-level}/?{How many recipients?})]] rounds}}!!!{{aoe=[Creature(s) touched](!rounds --target-nosave caster|@{selected|token_id}|Sertens-Immunity-casting|[[?{How many recipients?}]]|-1|Casting Serten\'s Spell Immunity on ?{How many recipients?} creatures takes ?{How many recipients?} rounds|stopwatch --target-nosave single|@{selected|token_id}|\\amp#64;{target|Who to give immunity to?|token_id}|Sertens-Immunity|[[floor(10*@{selected|mu-casting-level}/?{How many recipients?})]]|-1|Better saves against many spells - see PHB p192|white-tower)}}{{save=None}}{{reference=PHB p192}}{{Use=Select the first creature to be given immunity using the *area of effect* button. Subsequent creatures to protect will be prompted for on subsequent turns of the caster. Additional save types are automatically added to creature\'s saving throw tables}}SpellData=[w:Sartens Spell Immunity,lv:8,sp:10,gp:500,cs:VSM]{{effects=Confer virtual immunity to certain spells and magical attack forms upon those he touches.}}{{hide1=For every four levels of experience of the wizard, one creature can be protected by the Serten\'s spell immunity spell; however, if more than one is protected, the duration of the protection is divided among the protected creatures.\nFor example, a 16th-level wizard can cast the spell upon one creature and it will last 16 turns, or place it upon two creatures for eight turns, or four creatures for four turns.) The protection gives a bonus to saving throws, according to spell type and level, as shown in the following table.\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;th\\ampgt;Spell Level\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Wizard Spell\\amplt;/th\\ampgt;\\amplt;th\\ampgt;Priest Spell\\amplt;/th\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;1st-\\amplt;tr\\ampgt;\\amplt;td\\ampgt;3rd\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+9^\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+7\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;4th-6th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+7\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+5\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;7th-8th\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+5\\amplt;/td\\ampgt;\\amplt;td\\ampgt;+3\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\n^ Includes beguiling effects.}}{{materials=A diamond of at least 500 gp value, which must be crushed and sprinkled over the spell recipients. Each such creature must also have in its possession a diamond of at least one carat size, intact and carried on its person}}\n!setattr --silent --charid @{selected|character_id} --SSI-creatures|?{How many recipients?}'},
+ {name:'Sink',type:'muspelll8',ct:'18',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nSink\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Enchantment, Alteration}}Specs=[Sink,MUspellL8,1H,Enchantment|Alteration]{{components=V,S}}{{time=[[8]]}}{{range=[[10*@{selected|mu-casting-level}]] yards}}{{duration=1 or 2 rounds}}{{aoe=1 creature or object, max [[[@{selected|mu-casting-level}]] cu.ft.](!rounds --aoe @{selected|token_id}|rectangle|feet|[[10*@{selected|mu-casting-level}]]|||magic)}}{{save=Special}}{{reference=PHB p192}}SpellData=[w:Sink,lv:8,sp:18,gp:0,cs:VS]{{effects=Force a creature or object into the very earth or floor upon which it stands.}}{{hide1=When casting the spell, the wizard must chant the spell for the remainder of the round without interruption. At that juncture, the subject creature or object becomes rooted to the spot unless a saving throw vs. spell (for a creature) or disintegration (for an object with magical properties) is successful. (Note: "magical properties" include those of magical items as listed in the Dungeon Master Guide, those of items enchanted or otherwise of magical origin, and those of items with protectiontype spells or with permanent magical properties or similar spells upon them.) Items of a nonmagical nature are not entitled to a saving throw. If a subject fails its saving throw, it becomes of slightly greater density than the surface upon which it stands.\nThe spellcaster now has the option of ceasing his spell and leaving the subject as it is, in which case the spell expires in four turns, and the subject returns to normal. If the caster proceeds with the spell (into the next round), the subject begins to sink slowly into the ground. Before any actions are taken in the new round, the subject sinks one-quarter of its height; after the first group acts, another quarter; after the second group acts, another; and at the end of the round, the victim is totally sunken into the ground.\nThis entombment places a creature or object in a state of suspended animation. The cessation of time means that the subject does not grow older. Bodily and other functions virtually cease, but the subject is otherwise unharmed. The subject exists in undamaged form in the surface into which it was sunk, its upper point as far beneath the surface as the subject has height--a 6-foot-tall victim will be 6 feet beneath the surface, while a 60-foot-tall subject will have its uppermost point 60 feet below ground level. If the ground around the subject is somehow removed, the spell is broken and the subject returns to normal, but it does not rise up. Spells such as dig, transmute rock to mud, and freedom (the reverse of the 9th-level spell imprisonment) will not harm the sunken creature or object and will often be helpful in recovering it. If a detect magic spell is cast over an area upon which a sink spell was used, it reveals a faint magical aura of undefinable nature, even if the subject is beyond detection range. If the subject is within range of the detection, the spell\'s schools can be discovered (alteration and enchantment).}}'},
+ {name:'Symbol',type:'muspelll8',ct:'8',charge:'uncharged',cost:'10000',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casts\nSymbol\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration/Summoning}}Specs=[Symbol,MUspellL8,1H,Conjuration-Summoning]{{components=V, S, M}}{{time=8}}{{range=Touch}}{{duration=Special}}{{aoe=Special}}{{save=Special}}{{reference=PHB p193}}SpellData=[w:Symbol,lv:8,sp:8,gp:10000,cs:VSM]{{effects=Creates magical runes affecting creatures that pass over, touch, or read the runes, or pass through a portal upon which the symbol is inscribed. \n**Death, Discord, Fear, Hopelessness, Insanity, Pain, Sleep, Stunning**}}{{hide1=Upon casting the spell, the wizard inscribes the symbol upon whatever surface he desires. Likewise, the spellcaster is able to place the symbol of his choice, using any one of the following:\n\\amplt;table width="100%"\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Death*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;One or more creatures, whose total hit points do not exceed 80, are slain.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Discord*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;All creatures are affected and immediately fall to loud bickering and arguing; there is a 50% probability that creatures of different alignments attack each other. The bickering lasts for 5d4 rounds, the fighting for 2d4 rounds.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Fear*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;This symbol creates an extra-strong fear spell, causing all creatures to save vs. spell with -4 penalties to the die roll, or panic and flee as if attacked by a fear spell.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Hopelessness*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;All creatures are affected and must turn back in dejection unless they save vs. spell. Affected creatures submit to the demands of any opponent--for example, surrender, get out, etc. The hopelessness lasts for 3d4 turns; during this period it is 25% probable that affected creatures take no action during any round, and 25% likely that those taking action turn back or retire from battle, as applicable.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Insanity*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;One or more creatures whose total hit points do not exceed 120 become insane and remain so, acting as if a confusion spell had been placed upon them, until a heal, restoration, or wish spell is used to remove the madness.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Pain*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;All creatures are afflicted with wracking pains shooting through their bodies, causing a -2 penalty to Dexterity and a -4 penalty to attack rolls for 2d10 turns.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Sleep*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;All creatures under 8+1 Hit Dice immediately fall into a catatonic slumber and cannot be awakened for 1d12+4 turns.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;tr\\ampgt;\\amplt;td\\ampgt;*Stunning*\\amplt;/td\\ampgt;\\amplt;td\\ampgt;One or more creatures whose total hit points do not exceed 160 are stunned and reeling for 3d4 rounds, dropping anything they are holding.\\amplt;/td\\ampgt;\\amplt;/tr\\ampgt;\\amplt;/table\\ampgt;\nThe type of symbol cannot be recognized without being read and thus activating its effects.\nThe material components of this spell are powdered black opal and diamond dust, worth not less than 5,000 gp each.}}{{materials=Powdered black opal and diamond dust, worth not less than 5,000 gp each.}}'},
+ {name:'Trap-The-Soul',type:'muspelll8',ct:'1',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.spellTemplate+'}{{title=@{selected|casting-name} casting\nTrap The Soul\nas a level @{selected|mu-casting-level} caster}}{{splevel=Level 8 Wizard}}{{school=Conjuration-Summoning}}Specs=[Trap The Soul,MUspellL8,1H,Conjuration-Summoning]{{components=V,S,M}}{{time=Special+1}}{{range=[[10]] yards}}{{duration=Permanent until broken}}{{aoe=1 creature}}{{save=Special}}{{reference=PHB p193}}SpellData=[w:Trap The Soul,lv:8,sp:1,gp:0,cs:VSM]{{effects=Forces the creature\'s life force (and its material body) into a special prison gem enchanted by the spellcaster.}}{{hide1=The creature must be seen by the caster when the final word is uttered.\nThe spell can be triggered in one of two ways. First, the final word of the spell can be spoken when the creature is within spell range. This allows magic resistance (if any) and a saving throw vs. spell to avoid the effect. If the creature\'s real name is spoken as well, any magic resistance is ignored and the saving throw vs. spell suffers a penalty of -2. If the saving throw is successful, the prison gem shatters.\nThe second method is far more insidious, for it tricks the victim into accepting a trigger object inscribed with the final spell word, automatically placing the creature\'s soul in the trap. To use this method, both the creature\'s true name and the trigger word must be inscribed on the trigger item when the gem is enchanted. A sympathy spell can also be placed on the trigger item. As soon as the subject creature picks up or accepts the trigger item, its life force is automatically transferred to the gem, without the benefit of magic resistance or saving throw.\nThe gem prison will hold the trapped entity indefinitely, or until the gem is broken and the life force is released, allowing the material body to reform. If the trapped creature is a powerful creature from another plane (which could mean a character trapped by an inhabitant of another plane when the character is not on the Prime Material Plane), it can be required to perform a service immediately upon being freed. Otherwise, the creature can go free once the gem imprisoning it is broken.\nBefore the actual casting of the trap the soul spell, the wizard must prepare the prison, a gem of at least 1,000 gp value for every Hit Die or level of experience possessed by the creature to be trapped (for example, it requires a gem of 10,000 gp value to trap a 10 Hit Die or 10th-level creature). If the gem is not valuable enough, it shatters when the entrapment is attempted. (Note that while characters have no concept of level as such, the value of the gem needed to trap an individual can be researched. Remember that this value can change over time as characters advance.) Creating the prison gem requires an enchant an item spell and the placement of a maze spell into the gem, thereby forming the prison to contain the life force.}}'},
]},
MU_Spells_DB_L9:{bio:'Magic User Spell Database: Level 1 v8.02 07/05/2024
This database holds the definitions and API calls to enact Level 9 Wizard Spells. Spells can be memorised, and once used disapear from memory, only being refreshed on a long rest (1st level spells can optionally be refreshed on a short rest). 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: v8.02 07/05/2024 Updated spell effects to use latest features, e.g. save mod table v8.01 09/04/2024 Split spells by level into separate databases for easier management. For earlier changes, see MU-Spells-DB',
@@ -9625,17 +9619,17 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
LibFunctions.evalAttr = function(v) {
function reRoll(m,n,p,r) { return LibFunctions.rollDice(n,p,r); };
var handoutIDs = LibFunctions.getHandoutIDs(),
- orig = String(v);
+ orig = String(v).match(/([^\[\]]+)\s*?([^\[]?\[[^\[].*\])?/i);
const rePar = /\([\d\+\-\*\/\.]+?\)/g,
reRange = /\d+\:\d+/g,
reDice = /(\d+)d(\d+)(?:r(\d+))?/ig,
reMinMax = /[Mthmaxinflorce\s\.\,\(\)\d\+\-\*\/]+/g;
try {
- v = String(v);
- if (!v || !v.length) {
+ if (!orig || !orig.length) {
return '';
} else {
+ v = orig[1];
v = v.replace(/;/g,',')
.replace(/\^\(/g,'Math.max(')
.replace(/v\(/g,'Math.min(')
@@ -9653,11 +9647,11 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
} while (rePar.test(v) || reRange.test(v) || reDice.test(v));
v = v.replace(reMinMax,eval).replace(/\-\-/g,'+').replace(/\+\-/g,'-');
} while (rePar.test(v) || reRange.test(v) || reDice.test(v));
- return v;
+ return String(v)+(orig[2] || '');
};
} catch (e) {
- LibFunctions.sendError('Invalid attribute value given: calculating "'+orig+'" but only **\'+ - * / ( ) : d ^ v ,\'** can be used. Current evaluation is '+v+'. See **[CommandMaster Help]('+fields.journalURL+handoutIDs.CommandMasterHelp+')** for allowed Creature attribute specification formats.');
- LibFunctions.sendCatchError('LibFunctions',null,e);
+ LibFunctions.sendError('Invalid attribute value given: calculating "'+orig[0]+'" but only **\'+ - * / ( ) : d r f c ^ v , ;\'** can be used. Current evaluation is '+v);
+// LibFunctions.sendCatchError('LibFunctions',null,e);
return v;
};
};
diff --git a/RPGMlibrary AD+D2e/script.json b/RPGMlibrary AD+D2e/script.json
index a5583b298..4b6945a78 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": "3.5.1",
- "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","1.5.05","1.5.06","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.3.3","2.3.4","3.0.0","3.0.1","3.0.2","3.1.3","3.2.0","3.2.1","3.3.0","3.4.0","3.5.0"],
+ "version": "3.5.2",
+ "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","1.5.05","1.5.06","2.1.0","2.2.0","2.2.1","2.2.2","2.3.0","2.3.1","2.3.2","2.3.3","2.3.4","3.0.0","3.0.1","3.0.2","3.1.3","3.2.0","3.2.1","3.3.0","3.4.0","3.5.0","3.5.1"],
"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 19ebda6091f2a268e2649f80c6f7b030a823cd27 Mon Sep 17 00:00:00 2001
From: DameryDad <74715860+DameryDad@users.noreply.github.com>
Date: Sat, 14 Sep 2024 17:01:16 +0100
Subject: [PATCH 2/2] Force Creature-A-E DB update
* Even though Race-DB-Creatures-A-E has not changed, users might have completed a temporary fix I documented, which now needs removing which this update does
---
RPGMlibrary AD+D2e/3.5.2/libRPGMaster2e.js | 6 +++---
RPGMlibrary AD+D2e/libRPGMaster2e.js | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/RPGMlibrary AD+D2e/3.5.2/libRPGMaster2e.js b/RPGMlibrary AD+D2e/3.5.2/libRPGMaster2e.js
index a342b6a2a..295300bfa 100644
--- a/RPGMlibrary AD+D2e/3.5.2/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/3.5.2/libRPGMaster2e.js
@@ -899,14 +899,14 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
{name:'Tallfellow-Halfling',type:'HumanoidRace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Tallfellow Halfling}}{{subtitle=Race}}Specs=[Tallfellow Halfling,HumanoidRace,0H,Humanoid]{{Alignment=Any (usually NG)}}{{Languages=Often *common, halfling, dwarf, elf, gnome, goblin, orc,* and any one Elven language}}{{Height=Males [40+2d8](!\\amp#13;\\amp#47;r 40+2d8 ins height)ins, Females [38+2d8](!\\amp#13;\\amp#47;r 38+2d8 ins height)ins}}{{Weight=Males [52+5d4](!\\amp#13;\\amp#47;r 52+5d4 lbs weight)lbs, Females [48+5d4](!\\amp#13;\\amp#47;r 48+5d4 lbs weight)lbs}}{{Life Expectancy=Average at 180 years}}{{Section=**Attributes**}}{{Minimum=Con:10, Dex:8, Int:6, Wis:7, Chr:5}}{{Maximum=Str:17, Dex:19, Wis:19}}{{Adjustment=Wis *or* Dex:+1, Str:-1}}{{Section1=**Powers**}}{{Section2=None}}{{Section3=**Special Advantages**}}{{Secret Doors=Like elves, a Tallfellow can recognize a secret door on a [1 in 6](!\\amp#13;\\amp#47;r 1d6\\lt1) if passing within 10 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}}{{Hide in Wood=Tallfellows receive a +2 bonus to surprise rolls when in forest or wooded terrain under all circumstances.}}{{Other 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.}}{{Section5=**Special Disadvantages**}}{{Infravision=***None***}}RaceData=[w:Tallfellow Halfling, attr:str=3:17|con=10|dex=8:19|int=6|wis=7:19|chr=5, align:any, weaps:any, ac:any, 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:1],[cl:PW,w:Elf Detect Secret Doors,lv:0,sp:0,pd:-1]{{desc=This subrace of halflings is not so common as the Stout or Hairfoot but exists in significant numbers in many areas of temperate woodland. Averaging a little over 4\' in height, Tallfellows are slender and light-boned, weighing little more than the average Hairfoot.\nThey enjoy the company of elves, and most Tallfellow villages will be found nearby populations of that sylvan folk, with a flourishing trade between the two peoples.\nTallfellows display the greatest affinity toward working with wood of any halfling. They make splendid carpenters (often building boats or wagons for human customers), as well as loggers, carvers, pipesmiths, musicians, shepherds, liverymen, dairymen, cheesemakers, hunters, and scouts. They are better farmers than Stouts (although not as good as Hairfeet) and more adept than any other subrace at harvesting natural bounties of berries, nuts, roots, and wild grains.\nThe only halflings who enjoy much proficiency at riding, Tallfellows favor small ponies. Indeed, many unique breeds of diminutive horse have been bred among Tallfellow clans: fast, shaggy-maned, nimble mounts with great endurance. In a charge, of course, they lack the impact of a human-mounted warhorse; nonetheless, Tallfellow companies have served admirably as light lancers and horsearchers during many a hardfought campaign.\nOn foot, Tallfellows wield spears with rare skill. They are adept at forming bristling `porcupine\' formations with these weapons, creating such a menacing array that horses and footmen alike are deterred from attacking. This is one of the few halfling formations capable of standing toe-to-toe with a larger opponent in the open field.}}'},
{name:'Tinker-Gnome',type:'HumanoidRace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Tinker Gnome}}{{subtitle=Race}}Specs=[Tinker Gnome,HumanoidRace,0H,Gnome]{{Alignment=Any (Usually NG)}}{{Languages=*Tinker Gnome, Gnome Common, various human tongues*}}{{Height=Males [38+1d6](!\\amp#13;\\amp#47;r 38+1d6 ins height)ins, Females [36+1d6](!\\amp#13;\\amp#47;r 36+1d6 ins height)ins}}{{Weight=Males [72+5d4](!\\amp#13;\\amp#47;r 72+5d4 lbs weight)lbs, Females [68+5d4](!\\amp#13;\\amp#47;r 68+5d4 lbs weight)lbs}}{{Life Expectancy=250 to 300 years (rare)}}{{Section=**Attributes**}}{{Minimum=Str:6, Con:8, Dex:8, Int:8}}{{Maximum=Wis:12}}{{Adjustment=Dex:+2, Str:-1, Wis:-1}}{{Section1=**Powers**}}{{Expert Miners=Detect slopes, unsafe walls, cielings \\amp floors, determine approximate depth and direction underground}}{{Section3=**Special Advantages**}}{{Infravision=*Infravision* to 60ft.}}{{Magic Resistance=Gnomes are 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.}}{{Attack bonus=+1 To Hit kobolds and goblins}}{{Small size=Gnolls, bugbears, ogres, trolls, ogre magi, giants, and titans suffer a -4 penalty to attack}}{{Section5=**Special Disadvantages**}}{{Item failure=20% chance for failure of any magical item except weapons, armor, shields, illusionist items, and (if the character is a thief) items that duplicate thieving abilities.}}RaceData=[w:Tinker Gnome, attr:str=6|con=8|Dex=8|int=8|Wis=3:12]{{desc=The Tinkers are a very courageous and curious bunch of gnomes.\nTinkers resemble the rest of gnomedom - in the fact that they do value various types of stones, attributing to them great and supernatural powers. However, whereas the other subraces seek gems, the Tinkers hold a different substance as the grandest rock of all: coal. The Tinkers hold that coal (also known as the "Father of Steam") is the most valuable substance of the world, and those places where it can be mined quickly become Tinker Gnome warrens.\nIn size and stature, the Tinkers resemble Rock Gnomes--so much so that the difference is not immediately apparent, at least when based only upon appearance.\nTinkers who live out their lives can attain an age of 250 or 300 years, but it must be noted that this is a rare occurrence among the members of this subrace. If one of his or her own inventions doesn\'t do a Tinker in, chances are good that one of his or her neighbor\'s gadgets will.\nEven in childhood, Tinkers are encouraged to experiment with gadgets and gimmicks, trying different means of making things to perform tasks that could otherwise be easily done by hand. The Tinker reaches adulthood at about the age of fifty (by which time perhaps 10-15% of them have already succumbed to the common fate of their kind). Despite this high attrition, it\'s not until maturity that a Tinker Gnome\'s activities begin to get really dangerous.\nUpon reaching adulthood, the Tinker Gnome must select a guild for himself or herself. The number of guilds available varies by location, but in Mount Nevermind on Krynn--which is the center of Tinker civilization and by far the largest community of these inventive creatures anywhere--there are more than 150 active guilds. These include virtually all areas of practical endeavor, and quite a few impractical ones as well.\nAfter selecting a guild, each member of the subrace settles upon a Life-quest. The actual choice of the quest may take several decades, but once it has been decided, it becomes the reason behind that Tinker\'s existence. The Lifequest is an attempt to reach a perfect understanding of some device (anything from a spelljamming helm to a screw), a task at which the Tinker very rarely succeeds. Indeed, the best estimate is that less than 1% of these gnomes ever do fully grasp the nature of the object that has occupied their attention for so much of their adult lives; the rest of these easily-distracted gnomes get hopelessly sidetracked somewhere along the way.\nDespite the vagaries of their existence, the Tinkers are a fun-loving and generally sociable race. Their speech is unique in both its speed and complexity. Two Tinkers can rattle off information and opinion to each other in a succession of thousand-word sentences, speaking simultaneously and yet listening and understanding (as much as is possible, given the esoteric nature of many discussions) each other even as they voice their own points of view. Those Tinkers who have had some experience interacting with other races have learned to slow the pace of their communication but never quite overcome their frustration with those who can\'t talk and listen at the same time.}}'},
]},
- Race_DB_Creatures_A_E:{bio:'Creatures Database v2.02 14/10/2023
This sheet holds definitions of pre-defined creatures from The Monsterous Compendium that can be used by the RPGMaster API system (creatures can also be added directly to a character sheet by editing the Monster tab on the sheet). The definitions include automatically setable attributes, valid alignments, the weapons & armour each creature can use, bonuses and penalties to saves, attacks, surprise etc, and the powers that the creature gets. Depending on API configuration, the APIs can restrict creatures to these specifications, or not as desired.',
- gmnotes:'Change Log: v2.02 14/10/2023 Fixed issue with War Dog & added Leopard & Snow Leopard v2.01 29/09/2023 Added several families of Giants, and all Chromatic & Metalic Dragons, Titans, & others with substantial functional upgrades v1.34 24/09/2023 Fixed issues with Goblin definition v1.33 13/08/2023 Added a basic chest to act as the basis for the *Drag & Drop* container system v1.32 11/07/2023 Added creatures that can be contained in an Iron Flask v1.31 07/06/2023 Corrected some spattk & spdef entries with wrong syntax v1.30 30/04/2023 Added creatures to support Figurines of Wonderous Power and other MIs v1.28 03/03/2023 Added Elephant, Rhino and Mouse to support Wand of Wonder v1.27 12/02/2023 Added Adder as a creature to support Staff of the Serpent (Adder) v1.26 16/01/2023 Added both attkmsg & dmgmsg to display with attack & damage respectively. v1.25 14/01/2023 Switched round creature attack names and dice rolls so will work with character sheet buttons as well as APIs v1.15-24 16/12/2022 Added more creatures and changed format for inherrited template fields v1.14 25/11/2022 Added more creatures, especially undead at DM request v1.10 14/11/2022 Initial live release of a sample creatures database v1.02 10/11/2022 Fixes and additional creatures v1.01 01/11/2022 First version of Race-DB-Creatures',
+ Race_DB_Creatures_A_E:{bio:'Creatures Database v2.04 14/09/2024
This sheet holds definitions of pre-defined creatures from The Monsterous Compendium that can be used by the RPGMaster API system (creatures can also be added directly to a character sheet by editing the Monster tab on the sheet). The definitions include automatically setable attributes, valid alignments, the weapons & armour each creature can use, bonuses and penalties to saves, attacks, surprise etc, and the powers that the creature gets. Depending on API configuration, the APIs can restrict creatures to these specifications, or not as desired.',
+ gmnotes:'Change Log: v2.04 14/09/2024 Version change to force deletion of any extracted databases used for temporary fixes v2.02 14/10/2023 Fixed issue with War Dog & added Leopard & Snow Leopard v2.01 29/09/2023 Added several families of Giants, and all Chromatic & Metalic Dragons, Titans, & others with substantial functional upgrades v1.34 24/09/2023 Fixed issues with Goblin definition v1.33 13/08/2023 Added a basic chest to act as the basis for the *Drag & Drop* container system v1.32 11/07/2023 Added creatures that can be contained in an Iron Flask v1.31 07/06/2023 Corrected some spattk & spdef entries with wrong syntax v1.30 30/04/2023 Added creatures to support Figurines of Wonderous Power and other MIs v1.28 03/03/2023 Added Elephant, Rhino and Mouse to support Wand of Wonder v1.27 12/02/2023 Added Adder as a creature to support Staff of the Serpent (Adder) v1.26 16/01/2023 Added both attkmsg & dmgmsg to display with attack & damage respectively. v1.25 14/01/2023 Switched round creature attack names and dice rolls so will work with character sheet buttons as well as APIs v1.15-24 16/12/2022 Added more creatures and changed format for inherrited template fields v1.14 25/11/2022 Added more creatures, especially undead at DM request v1.10 14/11/2022 Initial live release of a sample creatures database v1.02 10/11/2022 Fixes and additional creatures v1.01 01/11/2022 First version of Race-DB-Creatures',
root:'Race-DB',
api:'cmd',
type:'class,race',
controlledby:'all',
avatar:'https://s3.amazonaws.com/files.d20.io/images/241737383/GL25pkAS2z5JJ4S9cMKkjw/max.png?1629918721',
- version:2.03,
+ version:2.04,
db:[{name:'Adder',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'%{Race-DB-Creatures|Poison-Snake-20}{{}}Specs=[Poison Snake,CreatureRace,0H,Poison Snake 20]{{}}RaceData=[w:Poison Snake 20]{{title=Adder}}'},
{name:'Advanced-Bullywug',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=, Advanced}}RaceData=[w:Advanced Bullywug, cattr:int=8:10|size=M]{{subtitle=Creature}}%{Race-DB-Creatures|Bullywug}{{Intelligence=Average (8 to 10)}}{{Size=M, 5-6ft tall}}Specs=[Bullywug Leader,CreatureRace,0H,Bullywug]{{desc1=**Advanced Bullywug:** A small number of bullywugs are larger and more intelligent than the rest of their kind. These bullywugs make their homes in abandoned buildings and caves, and send out regular patrols and hunting parties. These groups tend to be well equipped and organized, and stake out a regular territory, which varies with the size of the group. They are more aggressive than their smaller cousins, and will fight not only other bullywugs but other monsters as well. The intelligent bullywugs also organize regular raids outside their territory for food and booty, and especially prize human flesh. Since they are chaotic evil, all trespassers, including other bullywugs, are considered threats or sources of food.}}'},
{name:'Advanced-Bullywug-Shaman',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=, Advanced Shaman}}RaceData=[w:Advanced Bullywug Shaman, cattr:int=8:10|size=M|cl=pr:Shaman|lv=2]{{subtitle=Creature}}%{Race-DB-Creatures|Bullywug}{{Intelligence=Average (8 to 10)}}{{Size=M, 5-6ft tall}}Specs=[Advanced Bullywug Shaman,CreatureRace,0H,Bullywug]{{desc=**Advanced Bullywug Shaman:** For every 10 advanced bullywugs in a community, there is a 10% chance of a 2nd-level shaman being present. The creature requires the spellbook setting up, and spells to be memorised}}'},
diff --git a/RPGMlibrary AD+D2e/libRPGMaster2e.js b/RPGMlibrary AD+D2e/libRPGMaster2e.js
index a342b6a2a..295300bfa 100644
--- a/RPGMlibrary AD+D2e/libRPGMaster2e.js
+++ b/RPGMlibrary AD+D2e/libRPGMaster2e.js
@@ -899,14 +899,14 @@ const libRPGMaster = (() => { // eslint-disable-line no-unused-vars
{name:'Tallfellow-Halfling',type:'HumanoidRace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Tallfellow Halfling}}{{subtitle=Race}}Specs=[Tallfellow Halfling,HumanoidRace,0H,Humanoid]{{Alignment=Any (usually NG)}}{{Languages=Often *common, halfling, dwarf, elf, gnome, goblin, orc,* and any one Elven language}}{{Height=Males [40+2d8](!\\amp#13;\\amp#47;r 40+2d8 ins height)ins, Females [38+2d8](!\\amp#13;\\amp#47;r 38+2d8 ins height)ins}}{{Weight=Males [52+5d4](!\\amp#13;\\amp#47;r 52+5d4 lbs weight)lbs, Females [48+5d4](!\\amp#13;\\amp#47;r 48+5d4 lbs weight)lbs}}{{Life Expectancy=Average at 180 years}}{{Section=**Attributes**}}{{Minimum=Con:10, Dex:8, Int:6, Wis:7, Chr:5}}{{Maximum=Str:17, Dex:19, Wis:19}}{{Adjustment=Wis *or* Dex:+1, Str:-1}}{{Section1=**Powers**}}{{Section2=None}}{{Section3=**Special Advantages**}}{{Secret Doors=Like elves, a Tallfellow can recognize a secret door on a [1 in 6](!\\amp#13;\\amp#47;r 1d6\\lt1) if passing within 10 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}}{{Hide in Wood=Tallfellows receive a +2 bonus to surprise rolls when in forest or wooded terrain under all circumstances.}}{{Other 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.}}{{Section5=**Special Disadvantages**}}{{Infravision=***None***}}RaceData=[w:Tallfellow Halfling, attr:str=3:17|con=10|dex=8:19|int=6|wis=7:19|chr=5, align:any, weaps:any, ac:any, 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:1],[cl:PW,w:Elf Detect Secret Doors,lv:0,sp:0,pd:-1]{{desc=This subrace of halflings is not so common as the Stout or Hairfoot but exists in significant numbers in many areas of temperate woodland. Averaging a little over 4\' in height, Tallfellows are slender and light-boned, weighing little more than the average Hairfoot.\nThey enjoy the company of elves, and most Tallfellow villages will be found nearby populations of that sylvan folk, with a flourishing trade between the two peoples.\nTallfellows display the greatest affinity toward working with wood of any halfling. They make splendid carpenters (often building boats or wagons for human customers), as well as loggers, carvers, pipesmiths, musicians, shepherds, liverymen, dairymen, cheesemakers, hunters, and scouts. They are better farmers than Stouts (although not as good as Hairfeet) and more adept than any other subrace at harvesting natural bounties of berries, nuts, roots, and wild grains.\nThe only halflings who enjoy much proficiency at riding, Tallfellows favor small ponies. Indeed, many unique breeds of diminutive horse have been bred among Tallfellow clans: fast, shaggy-maned, nimble mounts with great endurance. In a charge, of course, they lack the impact of a human-mounted warhorse; nonetheless, Tallfellow companies have served admirably as light lancers and horsearchers during many a hardfought campaign.\nOn foot, Tallfellows wield spears with rare skill. They are adept at forming bristling `porcupine\' formations with these weapons, creating such a menacing array that horses and footmen alike are deterred from attacking. This is one of the few halfling formations capable of standing toe-to-toe with a larger opponent in the open field.}}'},
{name:'Tinker-Gnome',type:'HumanoidRace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=Tinker Gnome}}{{subtitle=Race}}Specs=[Tinker Gnome,HumanoidRace,0H,Gnome]{{Alignment=Any (Usually NG)}}{{Languages=*Tinker Gnome, Gnome Common, various human tongues*}}{{Height=Males [38+1d6](!\\amp#13;\\amp#47;r 38+1d6 ins height)ins, Females [36+1d6](!\\amp#13;\\amp#47;r 36+1d6 ins height)ins}}{{Weight=Males [72+5d4](!\\amp#13;\\amp#47;r 72+5d4 lbs weight)lbs, Females [68+5d4](!\\amp#13;\\amp#47;r 68+5d4 lbs weight)lbs}}{{Life Expectancy=250 to 300 years (rare)}}{{Section=**Attributes**}}{{Minimum=Str:6, Con:8, Dex:8, Int:8}}{{Maximum=Wis:12}}{{Adjustment=Dex:+2, Str:-1, Wis:-1}}{{Section1=**Powers**}}{{Expert Miners=Detect slopes, unsafe walls, cielings \\amp floors, determine approximate depth and direction underground}}{{Section3=**Special Advantages**}}{{Infravision=*Infravision* to 60ft.}}{{Magic Resistance=Gnomes are 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.}}{{Attack bonus=+1 To Hit kobolds and goblins}}{{Small size=Gnolls, bugbears, ogres, trolls, ogre magi, giants, and titans suffer a -4 penalty to attack}}{{Section5=**Special Disadvantages**}}{{Item failure=20% chance for failure of any magical item except weapons, armor, shields, illusionist items, and (if the character is a thief) items that duplicate thieving abilities.}}RaceData=[w:Tinker Gnome, attr:str=6|con=8|Dex=8|int=8|Wis=3:12]{{desc=The Tinkers are a very courageous and curious bunch of gnomes.\nTinkers resemble the rest of gnomedom - in the fact that they do value various types of stones, attributing to them great and supernatural powers. However, whereas the other subraces seek gems, the Tinkers hold a different substance as the grandest rock of all: coal. The Tinkers hold that coal (also known as the "Father of Steam") is the most valuable substance of the world, and those places where it can be mined quickly become Tinker Gnome warrens.\nIn size and stature, the Tinkers resemble Rock Gnomes--so much so that the difference is not immediately apparent, at least when based only upon appearance.\nTinkers who live out their lives can attain an age of 250 or 300 years, but it must be noted that this is a rare occurrence among the members of this subrace. If one of his or her own inventions doesn\'t do a Tinker in, chances are good that one of his or her neighbor\'s gadgets will.\nEven in childhood, Tinkers are encouraged to experiment with gadgets and gimmicks, trying different means of making things to perform tasks that could otherwise be easily done by hand. The Tinker reaches adulthood at about the age of fifty (by which time perhaps 10-15% of them have already succumbed to the common fate of their kind). Despite this high attrition, it\'s not until maturity that a Tinker Gnome\'s activities begin to get really dangerous.\nUpon reaching adulthood, the Tinker Gnome must select a guild for himself or herself. The number of guilds available varies by location, but in Mount Nevermind on Krynn--which is the center of Tinker civilization and by far the largest community of these inventive creatures anywhere--there are more than 150 active guilds. These include virtually all areas of practical endeavor, and quite a few impractical ones as well.\nAfter selecting a guild, each member of the subrace settles upon a Life-quest. The actual choice of the quest may take several decades, but once it has been decided, it becomes the reason behind that Tinker\'s existence. The Lifequest is an attempt to reach a perfect understanding of some device (anything from a spelljamming helm to a screw), a task at which the Tinker very rarely succeeds. Indeed, the best estimate is that less than 1% of these gnomes ever do fully grasp the nature of the object that has occupied their attention for so much of their adult lives; the rest of these easily-distracted gnomes get hopelessly sidetracked somewhere along the way.\nDespite the vagaries of their existence, the Tinkers are a fun-loving and generally sociable race. Their speech is unique in both its speed and complexity. Two Tinkers can rattle off information and opinion to each other in a succession of thousand-word sentences, speaking simultaneously and yet listening and understanding (as much as is possible, given the esoteric nature of many discussions) each other even as they voice their own points of view. Those Tinkers who have had some experience interacting with other races have learned to slow the pace of their communication but never quite overcome their frustration with those who can\'t talk and listen at the same time.}}'},
]},
- Race_DB_Creatures_A_E:{bio:'Creatures Database v2.02 14/10/2023
This sheet holds definitions of pre-defined creatures from The Monsterous Compendium that can be used by the RPGMaster API system (creatures can also be added directly to a character sheet by editing the Monster tab on the sheet). The definitions include automatically setable attributes, valid alignments, the weapons & armour each creature can use, bonuses and penalties to saves, attacks, surprise etc, and the powers that the creature gets. Depending on API configuration, the APIs can restrict creatures to these specifications, or not as desired.',
- gmnotes:'Change Log: v2.02 14/10/2023 Fixed issue with War Dog & added Leopard & Snow Leopard v2.01 29/09/2023 Added several families of Giants, and all Chromatic & Metalic Dragons, Titans, & others with substantial functional upgrades v1.34 24/09/2023 Fixed issues with Goblin definition v1.33 13/08/2023 Added a basic chest to act as the basis for the *Drag & Drop* container system v1.32 11/07/2023 Added creatures that can be contained in an Iron Flask v1.31 07/06/2023 Corrected some spattk & spdef entries with wrong syntax v1.30 30/04/2023 Added creatures to support Figurines of Wonderous Power and other MIs v1.28 03/03/2023 Added Elephant, Rhino and Mouse to support Wand of Wonder v1.27 12/02/2023 Added Adder as a creature to support Staff of the Serpent (Adder) v1.26 16/01/2023 Added both attkmsg & dmgmsg to display with attack & damage respectively. v1.25 14/01/2023 Switched round creature attack names and dice rolls so will work with character sheet buttons as well as APIs v1.15-24 16/12/2022 Added more creatures and changed format for inherrited template fields v1.14 25/11/2022 Added more creatures, especially undead at DM request v1.10 14/11/2022 Initial live release of a sample creatures database v1.02 10/11/2022 Fixes and additional creatures v1.01 01/11/2022 First version of Race-DB-Creatures',
+ Race_DB_Creatures_A_E:{bio:'Creatures Database v2.04 14/09/2024
This sheet holds definitions of pre-defined creatures from The Monsterous Compendium that can be used by the RPGMaster API system (creatures can also be added directly to a character sheet by editing the Monster tab on the sheet). The definitions include automatically setable attributes, valid alignments, the weapons & armour each creature can use, bonuses and penalties to saves, attacks, surprise etc, and the powers that the creature gets. Depending on API configuration, the APIs can restrict creatures to these specifications, or not as desired.',
+ gmnotes:'Change Log: v2.04 14/09/2024 Version change to force deletion of any extracted databases used for temporary fixes v2.02 14/10/2023 Fixed issue with War Dog & added Leopard & Snow Leopard v2.01 29/09/2023 Added several families of Giants, and all Chromatic & Metalic Dragons, Titans, & others with substantial functional upgrades v1.34 24/09/2023 Fixed issues with Goblin definition v1.33 13/08/2023 Added a basic chest to act as the basis for the *Drag & Drop* container system v1.32 11/07/2023 Added creatures that can be contained in an Iron Flask v1.31 07/06/2023 Corrected some spattk & spdef entries with wrong syntax v1.30 30/04/2023 Added creatures to support Figurines of Wonderous Power and other MIs v1.28 03/03/2023 Added Elephant, Rhino and Mouse to support Wand of Wonder v1.27 12/02/2023 Added Adder as a creature to support Staff of the Serpent (Adder) v1.26 16/01/2023 Added both attkmsg & dmgmsg to display with attack & damage respectively. v1.25 14/01/2023 Switched round creature attack names and dice rolls so will work with character sheet buttons as well as APIs v1.15-24 16/12/2022 Added more creatures and changed format for inherrited template fields v1.14 25/11/2022 Added more creatures, especially undead at DM request v1.10 14/11/2022 Initial live release of a sample creatures database v1.02 10/11/2022 Fixes and additional creatures v1.01 01/11/2022 First version of Race-DB-Creatures',
root:'Race-DB',
api:'cmd',
type:'class,race',
controlledby:'all',
avatar:'https://s3.amazonaws.com/files.d20.io/images/241737383/GL25pkAS2z5JJ4S9cMKkjw/max.png?1629918721',
- version:2.03,
+ version:2.04,
db:[{name:'Adder',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'%{Race-DB-Creatures|Poison-Snake-20}{{}}Specs=[Poison Snake,CreatureRace,0H,Poison Snake 20]{{}}RaceData=[w:Poison Snake 20]{{title=Adder}}'},
{name:'Advanced-Bullywug',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=, Advanced}}RaceData=[w:Advanced Bullywug, cattr:int=8:10|size=M]{{subtitle=Creature}}%{Race-DB-Creatures|Bullywug}{{Intelligence=Average (8 to 10)}}{{Size=M, 5-6ft tall}}Specs=[Bullywug Leader,CreatureRace,0H,Bullywug]{{desc1=**Advanced Bullywug:** A small number of bullywugs are larger and more intelligent than the rest of their kind. These bullywugs make their homes in abandoned buildings and caves, and send out regular patrols and hunting parties. These groups tend to be well equipped and organized, and stake out a regular territory, which varies with the size of the group. They are more aggressive than their smaller cousins, and will fight not only other bullywugs but other monsters as well. The intelligent bullywugs also organize regular raids outside their territory for food and booty, and especially prize human flesh. Since they are chaotic evil, all trespassers, including other bullywugs, are considered threats or sources of food.}}'},
{name:'Advanced-Bullywug-Shaman',type:'creaturerace',ct:'0',charge:'uncharged',cost:'0',body:'\\amp{template:'+fields.defaultTemplate+'}{{name=, Advanced Shaman}}RaceData=[w:Advanced Bullywug Shaman, cattr:int=8:10|size=M|cl=pr:Shaman|lv=2]{{subtitle=Creature}}%{Race-DB-Creatures|Bullywug}{{Intelligence=Average (8 to 10)}}{{Size=M, 5-6ft tall}}Specs=[Advanced Bullywug Shaman,CreatureRace,0H,Bullywug]{{desc=**Advanced Bullywug Shaman:** For every 10 advanced bullywugs in a community, there is a 10% chance of a 2nd-level shaman being present. The creature requires the spellbook setting up, and spells to be memorised}}'},
| |