Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Spell slot usage

I'm probably searching the wrong terms, but I haven't been able to find something on this yet. I'm using the 5e D&D by Roll20 character sheet (I do have the companion script for this and it works as it's expected), and I've been trying to put together simplified/one-button macros for some of the more complex spells a few of my PCs use, but in order to get these macros to be all-encompassing, I really want to be able to use the required spell slots. Example: Spiritual Weapon.  The cleric clicks the spell the first time to cast, the companion script reduces/uses the spell slot. Then his next turn, he has to click the spell again to make an attack, and the companion script uses the spell slot again. I also have a script that auto-creates the token my cleric uses for the weapon and places it next to the character token, ready to be used. What I would like to do is create a token macro (probably a drop-down query) that can call a script to: "Cast" the spell, using spell slot and create token Roll attack and damage without using another spell slot Allow for upcasting I have the same situation that I'm trying to resolve for a sorcerer in my group who uses Storm Sphere, which, after the initial cast, has several addtional attacks/damage that can be used each turn. I want 1 button to cast the spell (maybe place a spell template on the map for marking), then on future turns, allow the sorcerer to easily roll the storm arc attack/damage or burst damage without using addtional spell slots or having to manually select and roll the dice each time Any suggestions would be greatly appreciated. Thank you all very much.
There is an excellent suggestion from Keith on how to handle spells like this. This works well for Scorching Ray which was my specific example.
Doug E. said: There is an excellent suggestion from Keith on how to handle spells like this. This works well for Scorching Ray which was my specific example. That's a great suggestion, thanks for pointing me to that. I'll definitely try something like that out.  I find it odd that they still haven't included API access to the spell slots on this sheet, seems like a basic functionality that lots of scripters would want available  
1640410455
Oosh
Sheet Author
API Scripter
Cam said: I find it odd that they still haven't included API access to the spell slots on this sheet, seems like a basic functionality that lots of scripters would want available The spell slots are just Attributes, which the API absolutely has access to. What did you want a script to do, exactly?
For Spiritual Weapon I can share this piece of code, which is creating a token, giving it an attack ability and granting the player access to the token. maybe it is that what you are looking for. The function is embedded in the "custom spell book" by Nick O. . var pxSize = 70; var pageID = token.get("pageid"); var curPage = (findObjs({_type: "page", _id: pageID})[0]||{get:()=>''}); //var curPageScale = curPage.get("scale_number"); var curPageFactor = curPage.get("snapping_increment"); var stdPxDist = pxSize*curPageFactor; function spiritualWeapon(spellLevel, tok, player, tokenName,stdPxDist){   var tokImage = LINKTOIMAGE ;   var namePart = "Spiritual Weapon";   //+ @{${tokenName}|spellcasting_ability}     var abb = `&{template:default} {{name=Spiritual Weapon}}{{attack =[[1d20+@{${tokenName}|spell_attack_bonus}]] }} {{damage = [[ @{${tokenName}|spellcasting_ability}((${spellLevel}/2)-0.5)d8]]}}`;    //{{Spiritual Weapon attack hits AC [[1d20+@{${tokenName}|spell_attack_bonus}]]= It inflicts [[${numDice}d8]] force damage and [[${numDice}d8]] additional crit. damage, if applicable}}`;   var canName = tok.get("name")+"'s " + namePart;   //var  abb = `&{template:atkdmg}{{mod = @{${tokenName}|spell_attack_bonus}}}{{always=1}}{{rname = Spiritual Weapon Attack}}{{attack=1}}{{r1 = [[1d20]]cs>20}}{{damage=1}}{{dmg1flag=1}}{{dmg1 =[[((${spellLevel}/2)-0.5)d8]]}}{{dmg1type = force}}{{crit=1}}{{crit1=[[((${spellLevel}/2)-0.5)d8]]}}{{charname=canName}}`;   helpCharacter = findObjs({type:'character',name:canName})[0];   if(helpCharacter){      //char = findObjs({type:'character',name:canName})[0];       eldritchChar = getObj('character',helpCharacter.id);       var existingAbbs = findObjs({type: 'ability', characterid: helpCharacter.id});       _.each(existingAbbs, function(abil) {             abil.remove();         });       createObj('ability',{         characterid:eldritchChar.get("id"),         name:'Attack!',         action:abb,         istokenaction:true       });        let canTok = createObj('graphic',{       left:tok.get("left") + stdPxDist,       top:tok.get("top"),       height:stdPxDist,       width:stdPxDist,       pageid:tok.get("pageid"),       layer:"objects",       imgsrc: tokImage,       name:canName,       represents: eldritchChar.get("id"),       controlledby:player.get("id"),       isdrawing:false     });       setDefaultTokenForCharacter(eldritchChar, canTok);   } else{     let eldritchChar = createObj('character',{     name:canName,     inplayerjournals:player.get("id"),     controlledby:player.get("id")   })   createObj('ability',{     characterid:eldritchChar.get("id"),     name:'Attack!',     action:abb,     istokenaction:true   });   let canTok = createObj("graphic",{     left:tok.get("left") + stdPxDist,     top:tok.get("top"),     height:stdPxDist/2,     width:stdPxDist/2,     pageid:tok.get("pageid"),     layer:"objects",     imgsrc:tokImage,     name:canName,     represents: eldritchChar.get("id"),     controlledby:player.get("id"),     isdrawing:false   });   setDefaultTokenForCharacter(eldritchChar, canTok) }   sendChat(tok.get("name"), `I summoned a spiritual weapon at Level ${spellLevel}.`);   spawnFx(tok.get("left")+stdPxDist, tok.get("top"), "burst-holy", tok.get("pageid")); }
Oosh said: Cam said: I find it odd that they still haven't included API access to the spell slots on this sheet, seems like a basic functionality that lots of scripters would want available The spell slots are just Attributes, which the API absolutely has access to. What did you want a script to do, exactly? Trying to do the same thing the Companion script does; reduce the number of remaining spell slots when that spell is cast (and for up casting), and maybe allow for the little warning it gives at the last/no spell slots left. I haven't seen a way to do that yet. It's possible I've overlooked it though obviously.
Marco R. said: For Spiritual Weapon I can share this piece of code, which is creating a token, giving it an attack ability and granting the player access to the token. maybe it is that what you are looking for. The function is embedded in the "custom spell book" by Nick O. . var pxSize = 70; var pageID = token.get("pageid"); var curPage = (findObjs({_type: "page", _id: pageID})[0]||{get:()=>''}); //var curPageScale = curPage.get("scale_number"); var curPageFactor = curPage.get("snapping_increment"); var stdPxDist = pxSize*curPageFactor; function spiritualWeapon(spellLevel, tok, player, tokenName,stdPxDist){   var tokImage = LINKTOIMAGE ;   var namePart = "Spiritual Weapon";   //+ @{${tokenName}|spellcasting_ability}     var abb = `&{template:default} {{name=Spiritual Weapon}}{{attack =[[1d20+@{${tokenName}|spell_attack_bonus}]] }} {{damage = [[ @{${tokenName}|spellcasting_ability}((${spellLevel}/2)-0.5)d8]]}}`;    //{{Spiritual Weapon attack hits AC [[1d20+@{${tokenName}|spell_attack_bonus}]]= It inflicts [[${numDice}d8]] force damage and [[${numDice}d8]] additional crit. damage, if applicable}}`;   var canName = tok.get("name")+"'s " + namePart;   //var  abb = `&{template:atkdmg}{{mod = @{${tokenName}|spell_attack_bonus}}}{{always=1}}{{rname = Spiritual Weapon Attack}}{{attack=1}}{{r1 = [[1d20]]cs>20}}{{damage=1}}{{dmg1flag=1}}{{dmg1 =[[((${spellLevel}/2)-0.5)d8]]}}{{dmg1type = force}}{{crit=1}}{{crit1=[[((${spellLevel}/2)-0.5)d8]]}}{{charname=canName}}`;   helpCharacter = findObjs({type:'character',name:canName})[0];   if(helpCharacter){      //char = findObjs({type:'character',name:canName})[0];       eldritchChar = getObj('character',helpCharacter.id);       var existingAbbs = findObjs({type: 'ability', characterid: helpCharacter.id});       _.each(existingAbbs, function(abil) {             abil.remove();         });       createObj('ability',{         characterid:eldritchChar.get("id"),         name:'Attack!',         action:abb,         istokenaction:true       });        let canTok = createObj('graphic',{       left:tok.get("left") + stdPxDist,       top:tok.get("top"),       height:stdPxDist,       width:stdPxDist,       pageid:tok.get("pageid"),       layer:"objects",       imgsrc: tokImage,       name:canName,       represents: eldritchChar.get("id"),       controlledby:player.get("id"),       isdrawing:false     });       setDefaultTokenForCharacter(eldritchChar, canTok);   } else{     let eldritchChar = createObj('character',{     name:canName,     inplayerjournals:player.get("id"),     controlledby:player.get("id")   })   createObj('ability',{     characterid:eldritchChar.get("id"),     name:'Attack!',     action:abb,     istokenaction:true   });   let canTok = createObj("graphic",{     left:tok.get("left") + stdPxDist,     top:tok.get("top"),     height:stdPxDist/2,     width:stdPxDist/2,     pageid:tok.get("pageid"),     layer:"objects",     imgsrc:tokImage,     name:canName,     represents: eldritchChar.get("id"),     controlledby:player.get("id"),     isdrawing:false   });   setDefaultTokenForCharacter(eldritchChar, canTok) }   sendChat(tok.get("name"), `I summoned a spiritual weapon at Level ${spellLevel}.`);   spawnFx(tok.get("left")+stdPxDist, tok.get("top"), "burst-holy", tok.get("pageid")); } Thank you for this. It's very similar to what I'm already doing, but I hadn't thought about building a token action on the token I create that contains the attack. I will definitely play with this I think and see how my cleric player feels about using it like that. I could definitely do similar things with the Storm Sphere spell if I have that throw a specific spell template on the map too.
1640487501

Edited 1640487664
Oosh
Sheet Author
API Scripter
Check out line 308 of the Companion script . The resolveslot() function. That should be a good starting point - you're just looking at some very basic math with the lvlX_slots_expended attribute. Note that the attributes are rather stupidly named - the "expended" attribute actually tracks "remaining" slots. Oh, and the handleslotspell() function on line 262, that grabs the spell level from the macro output. And if you're going to crib from Companion, please do change the variable names to camelCase. My poor brain is trying to unfuck each one into multiple word combinations every time I look at that script. I think I did too many 9-letter word Targets as a youngster.
Well, regarding the spell slots I use this in my version of the customSpellBook: if(spellLevel>0){ sendChat("API",`!modbattr --charid ${charID} --lvl${spellLevel}_slots_expended|-1`); var finalMessage = `&{template:desc} {{desc= **Expanded a Level ${spellLevel} spell slot**}}`; sendChat("API", finalMessage) }