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

Macro for Returning Character Attribute by ID

The concept I have in mind seems fairly simple, but I'm not quite sure how to execute it. I essentially want to build a macro for a player, so he can essentially get the health of the other players at any time. I don't want to use @target because then they would be able to do it on any token, and I don't know if there is a way to return an attribute directly from the ID using only a macro. My original idea was to use a select query to choose from a list of characterIDs (that would be labeled with what characters they represent) and it would parse into a command that returns the proper result.
1523141577
The Aaron
Pro
API Scripter
Without using @{target}, an API script is probably the best option... !show-attr attribute attribute attribute -- character_id character_id character_id Example: !show-attr hp ac -- -Jh1tMI3qnsFKEV66BuA -KS8sEhi64TaYuVoQG9Q This whispers to the person that runs it the name of each character for the character ids passed to it (if they exist), and then the current status of each of the attributes listed (if they exist for the character): You can pre-build the command and put it in a macro, then give your cleric player access to it. The Script: on('ready',() => {   const resolveAttr = (cid,name) => ({     name: name,     current: getAttrByName(cid,name),     max: getAttrByName(cid,name,'max')   });   const makePrefixer = function(prefix){     let c = {};     return (val)=>{       val = val.trim();       c[val]=c[val]||0;       return prefix.repeat(c[val]++)+val;     };   };   const buildRows = (cs, as) => {     let p = makePrefixer(' ');     return cs.map( (c) =>       `{{${p(c.get('name'))}=<ul>${as[c.id].map((a)=>`<li><b>${a.name}:</b> ${a.current}${a.max?`/${a.max}`:''}</li>`).join('')}</ul>}}`     ).join('');   };   on('chat:message',(msg) => {     if('api'===msg.type && /^!show-attr\b/i.test(msg.content)){       let parts = msg.content.split(/\s+--\s+/);       let attrs = parts[0].split(/\s+/).splice(1);       let ids = (parts[1]||'').split(/\s+/);       let who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');       let attrmap = {};       let characters = ids.map((id) => getObj('character',id)).filter((t) => undefined !== t);       characters.forEach((c) => attrmap[c.id] = attrs.map((a) => resolveAttr(c.id,a) ).filter((a)=>undefined !== a.current));       sendChat('',`/w "${who}" &{template:default}{{name=Roster}}${buildRows(characters,attrmap)}`);     }   }); });
The Aaron said: Without using @{target}, an API script is probably the best option... Awesome script and I think I will add it to my library for future use, but can't you do this inline if you know the character's name or ID? Wouldn't they be able to use @{Character_Name|Attribute} Or get the character ID by outputting @{Character_Name|character_id} Then do @{character_id|attribute}
1523194717
The Aaron
Pro
API Scripter
Where @{target|ATTR} and @{selected|ATTR} will work, you can only pull attributes from a named character if you control that character, so @{NAME|ATTR} only works for the characters you can control.  Kind of strange and I only just learned this distinction a few nights ago (Thanks Franky!). =D
So I finally got around to implementing this! I have a question though, when using autocalc values it seems to not like it very much. I have another value character_health that is an autocalc of just the @{health} value if that's any simpler to use, but this seems to be a more deeply rooted problem in how the information is parsed.
1525915104
The Aaron
Pro
API Scripter
Hmm.. Try this version: on('ready',() => {   const resolveAttr = (cid,name) => ({     name: name,     current: getAttrByName(cid,name),     max: getAttrByName(cid,name,'max')   });   const makePrefixer = function(prefix){     let c = {};     return (val)=>{       val = val.trim();       c[val]=c[val]||0;       return prefix.repeat(c[val]++)+val;     };   };   const buildRows = (cs, as) => {     let p = makePrefixer(' ');     return cs.map( (c) =>       `{{${p(c.get('name'))}=<ul>${as[c.id].map((a)=>`<li><b>${a.name}:</b> [[${a.current}]]${a.max?`/[[${a.max}]]`:''}</li>`).join('')}</ul>}}`     ).join('');   };   on('chat:message',(msg) => {     if('api'===msg.type && /^!show-attr\b/i.test(msg.content)){       let parts = msg.content.split(/\s+--\s+/);       let attrs = parts[0].split(/\s+/).splice(1);       let ids = (parts[1]||'').split(/\s+/);       let who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');       let attrmap = {};       let characters = ids.map((id) => getObj('character',id)).filter((t) => undefined !== t);       characters.forEach((c) => attrmap[c.id] = attrs.map((a) => resolveAttr(c.id,a) ).filter((a)=>undefined !== a.current));       sendChat('',`/w "${who}" &{template:default}{{name=Roster}}${buildRows(characters,attrmap)}`);     }   }); });
!show-attr health h-head h-larm h-lleg h-torso h-rarm h-rleg -- -L9WcEc7nsSE9pCH_Quk Does not work, comes up with this: I repeated the same error using this query: !show-attr athletics_mod h-larm h-lleg h-torso h-rarm h-rleg -- -L9WardzyH-4B6lnO3kQ SyntaxError: Expected "(", ".", "[", "abs(", "ceil(", "d", "floor(", "round(", "t", "{", [ |\t], [+|\-] or [0-9] but "s" found. undefined But this query shows up fine: !show-attr h-head h-larm h-lleg h-torso h-rarm h-rleg -- -L9WcEc7nsSE9pCH_Quk
1525926292
The Aaron
Pro
API Scripter
Hmmm. Guess I need to think about this a bit more.