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

Loop Through Abilities on Abilities Tab

1530723828

Edited 1530723969
I'm attempting to create API buttons, dynamically.  Is it possible to loop through a selected character's list of abilities defined on the "Abilities" tab?  I know you can do this off of the sheet's repeating actions and such, but I want to build the buttons so they'll directly reference PowerCard macros I've set up as abilities. Example: [Warhammer](~@{selected|character_name}|Attack-Warhammer) Where the "Warhammer" and "Attack-Warhammer" portions would be dynamic based on the ability currently being pulled/looked at in the loop. Possible or just crazy talk? Thanks!
1530724494
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
You'd need to make an api script to do it, but with that, yes it is.
1530734514

Edited 1530734651
Almost there.  I was stumped before on how to do this, but played around a bit and have gotten close. var abilObj = findObjs({ _id: char.id, _type: "ability", }); _.each(abilObj, function(obj) { if (obj.name.slice(0, 6) == "Attack") { actionName = obj.name.slice(7); actionButton += '['+actionName+'](~@{'+char.get('name')+'}|'+obj.name+')<br>'; } }); However, I'm only getting one ability in the array ("Warhammer").  I have 2 ability macros setup being prefaced with "Attack".  Works perfectly if I could get everything that matches what I'm looking for.  I'm not seeing why.  I'm sure its something easy. :-P Thanks!
1530734987

Edited 1530735059
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
So, I'd do a few changes to your script: var abilObj = findObjs({ _id: char.id, _type: "ability", }); log('abilObj: '+JSON.stringify(abilObj));//Let's make sure of what we're getting _.each(abilObj, function(obj) { obj.name.replace(/^Attack\-+(.+)/i,(match,p1)=>{ actionButton += '['+p1+'](~@{'+char.get('name')+'}|'+obj.name+')\n'; }); }); I am assuming that char and actionName are defined elsewhere in your script.
1530793173

Edited 1530793527
Got it, finally!  Thanks for your advice, Scott.  This is what I came up with and it works great.  Its going to be expaned, later, to grab other abilitites, based on macro name prefix.  var abilObj = findObjs({ _type: "ability", _characterid: char.id, }); actionButtons = "<br><table><tr><td colspan=\"2\"><b>Actions:</b></td></tr>"; _.each(abilObj, function(obj) { if (obj.get("name").indexOf("Attack-") !== -1) { macroName = obj.get("name"); actionName = obj.get("name").substr(7).replace("-", " "); actionButtons += '<td>['+actionName+'](~@{'+charName+'}|'+macroName+')</td>'; }; });
1530796422
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
You're welcome, just passing on what the community has taught me. You can actually make this a lot easier to add additional menu types to. var abilObj = findObjs({ _type: "ability", _characterid: char.id, }); actionButtons = "<br><table><tr><td colspan=\"2\"><b>Actions:</b></td></tr>"; _.each(abilObj, function(obj) { if (obj.get("name").indexOf("Attack-") !== -1) {//This will be true if attack shows up anywhere in the name. That may be what you want, but just wanted to point it out. Also, if you really want to go with using an if statement, I'd use the javascript function startsWith instead of indexOf macroName = obj.get("name"); actionName = obj.get("name").substr(7).replace("-", " ");//using .substr makes this so that it will only work with attack at the start (or another 6 letter word), but if you want say spells you'll need to copy the code with a different subStr in it. actionButtons += '<td>['+actionName+'](~@{'+charName+'}|'+macroName+')</td>'; }; }); What I'd recommend: var abilObj = findObjs({ _type: "ability", _characterid: char.id, }); actionButtons = "<br><table><tr><td colspan=\"2\"><b>Actions:</b></td></tr>"; //Assume that you have some sort of command handler that processes a chat message like !menu --Attack to then send a menu of the selected character's attacks //Assume that this handler passes the menu type into this function via a variable named menuType _.each(abilObj, function(obj) { obj.get('name').replace(new RegExp('^'+menuType+'-(.*)','i'),(macroName,actionName)=>{//The regex will test the name of the obj and only proceed to the function if there's a match actionButtons += '<td>['+actionName+'](~@{'+charName+'}|'+macroName+')</td>'; }); });