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

searching attributes

1629818415

Edited 1629818516
Hi. I want to know if there's a syntax that allows me to search attributes based on a partial string, for grouping macros. For example, say I'm adding new specific injuries to each character using chatsetattr,  All new injury attributes begin with the string "inj" and I want to have them all send to chat so a character can view all of their current injuries without looking at their character sheet. The relevant added attributes might be @{injhead}, @{injlefthand}, and @{injrightbigtoe}. I want to have a macro (or api) that sends all of them at once with their current levels to chat, but leaves out any attribute that doesn't start with "inj". A character can just check their sheet of course, but I'm hopeful that there's a syntax that allows me to create an ability for a player, to check their current injury status from chat. Thanks.
1629820389
timmaugh
Pro
API Scripter
InsertArg can do that. You can build a menu of the injuries, and then output a "card" that would let them read the contents. See Keith's post  in that thread for more information on the technique.
1629827033
David M.
Pro
API Scripter
Does the InsertArgs "card" require the specific names of the attributes to be defined at runtime? Sounded kinda like the OP was looking for a "give me all attributes (and values, presumably) that start with the string "inj"
1629831505

Edited 1629835229
timmaugh
Pro
API Scripter
Oh, yeah, it works to do that, exactly. To Narrator's specific case... I added three injuries to a character, making sure they all began with "inj". Then I ran this macro (while speaking as that character): !ia --menu --title#puttext{{!!a#getme{{!!r#n}} !!b#` Injuries`}} --row#getrow{{!!t#Injuries !!c#ffffff !!s#getattrs{{!!c#getme{{}} !!op#br !!f#^f#inj !!frmt#fr#inj#``|uc}}}} And I got this output: Each button would whisper the injury to the player: Note that although the attributes all start with "inj", I executed a find/replace to remove that portion of the name, just to make the button text more readable. Alternatively, you could have the text of the injuries all report in that same menu (without having to click on a button): !ia --menu --title#puttext{{!!a#getme{{!!r#n}} !!b#` Injuries`}} --row#getrow{{!!r#elem !!f#.7 !!s#getattrs{{!!c#getme{{}} !!op#lve !!f#^f#inj !!frmt#fr#inj#``|uc}}}} Produces... And, for a more advanced usage, you could have a more complex naming scheme to have sections to your menu. Maybe that is by location... or maybe it is by effect: inj_movement_rightfoot inj_bleeding_chest inj_bleeding_rightarm inj_modifier_bleeding_head Whatever your classifications are (predefined list), they can become organizational structure to your menu. Given the list above, you'd want the Movement section to have one attribute, Bleeding to have 3, and Modifier to have one. Also, the head should show for both Bleeding and Modifier sections: That was produced by this command line: !ia --menu --title#puttext{{!!a#getme{{!!r#n}} !!b#` Injuries`}} --^^row#getrow{{!!t#MOVEMENT !!c#ffffff !!s#getattrs{{!!c#getme{{}} !!op#br !!f#^f#inj_|^f^#movement_ !!frmt#fr#inj_#``|fr#movement_#``|fr#bleeding_#``|fr#modifier_#``|uc}}}} --^^row#getrow{{!!t#BLEEDING !!c#ffffff !!s#getattrs{{!!c#getme{{}} !!op#br !!f#^f#inj_|^f^#bleeding_ !!frmt#fr#inj_#``|fr#movement_#``|fr#bleeding_#``|fr#modifier_#``|uc}}}} --row#getrow{{!!t#MODIFIER !!c#ffffff !!s#getattrs{{!!c#getme{{}} !!op#br !!f#^f#inj_|^f^#modifier_ !!frmt#fr#inj_#``|fr#movement_#``|fr#bleeding_#``|fr#modifier_#``|uc}}}} Just a few examples of what InsertArg can do to solve this usage case. Post back if you want a breakdown on what the lines are doing, or if you have trouble tweaking to your game setup.
1629832088

Edited 1629832274
David M.
Pro
API Scripter
EDIT - cross-posted! Tim's solution is prettier :)  - Hey, at least I got some experience messing with attributes Well, I had 40min to kill at work while waiting for some test results (and I wanted to eventually play with some attribute-related stuff for another script I'm working on since I hadn't worked with them in the API before), so I went ahead and put this script together. Syntax !injuries --CharName Looks for all attributes starting with "inj" (case insensitive) and displays the attribute name with the "inj" prefix removed. Has conditional output for current and max values, if exists. The script const InjuryReport = (() => { const version = '0.1.0'; const checkInstall = () => { log('-=> InjuryReport v'+version); }; const handleInput = (msg) => { if(msg.type=="api" && msg.content.indexOf("!injuries") === 0 ) { try { who = getObj('player',msg.playerid).get('_displayname'); let charName = msg.content.split(/--/)[1].trim(); let char = findObjs({ _type: "character", name: charName }); if (char[0] !== undefined) { var attrs = findObjs({ _type: "attribute", _characterid: char[0].get('_id') }, {caseInsensitive: true}); attrs = attrs.filter(att => att.get('name').toLowerCase().indexOf("inj") === 0); } else { sendChat('API', `/w "${who}"" Unable to find character named ${charName}`); return; } let output = `/w "${who}" &{template:default} {{name=${charName} Injury Report}} `; if (attrs.length === 0) { output = output + '{{N/A=}}'; } else { attrs.forEach(att => { let name = att.get('name').replace(/inj/i, ""); let current = att.get('current'); let max = att.get('max'); if (max !== "") { output = output + `{{${name}=${current} / ${max}}}`; } else { output = output + `{{${name}=${current}}}`; } }); } sendChat('API', output); } catch(err) { sendChat('API',`/w "${who}" Error: ${err.message}`); } }; }; const registerEventHandlers = () => { on('chat:message', handleInput); }; on('ready', () => { checkInstall(); registerEventHandlers(); }); })(); Example output (BigToe has current and max, Head only has current, and Tuchus contains a text string). The next character is uninjured.
1629832770
timmaugh
Pro
API Scripter
Don't contrast and compare! =D That's impressive work for 45 minutes, David! Mine took me several months to code up.
1629834496
David M.
Pro
API Scripter
Ha! I was just saying that the output looked really nice with that custom css.  I just re-used another scriplet I wrote months ago - there's probably only 15-ish lines of original code there, and most of the rest was stolen from Aaron's template, haha. I must admit I still haven't delved into InsertArgs yet. Looks so powerful, but the syntax seems the most intimidating to me of all the meta-scripts. 
1629835055
timmaugh
Pro
API Scripter
Yeah... IA is a bit of a misfit. And the syntax is... something else. It never quite made it to true meta-speed, either (because certain command lines require a roll query, etc.). I have plans to pull a lot of the pieces out as metascripts of their own (like a script that gets attributes for you: get me these attributes, filter them like this, format them like that, and leave THIS in the command line of the housing script). It all just takes time! =D
1630993949

Edited 1630994093
David M, your script is amazing, especially for basically being a brief exercise during a break at work. It really does exactly what you said it does. I noticed that the syntax only uses character name. What do I change so that it uses selected instead of name? That would enable a macro for all players to check their injuries.
1631012389
David M.
Pro
API Scripter
Try using  !injuries --@{selected|character_name}
Gracias.