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

OnMyTurn Modifications

I am working on a modification of The Aaron's OnMyTurn script for a few reasons.  1. So characters can have multiple entries that automatically kick off without them all being entered into one ability. 2. So I can store different abilities into different categories so I can look at a character and go "oh this is a magical ability" or "oh this is a game function" etc for my own personal mental needs. 3. But mainly so I can have the character's action menu automatically whispered to them at the beginning of their turn.  My question is fairly simple. Is there a way to amend the script so it pulls a macro/ability from a specific character sheet that everyone has access to? Or to write the Macro straight into the output of the API? Also, is there something in this API as written that sends to the chat twice and I am just not seeing it? on('ready', () => {     const resolver = (token,character) => (text) => {         const attrRegExp = /@{(?:([^|}]*)|(?:(selected)|(target)(?:\|([^|}]*))?)\|([^|}]*))(?:\|(max|current))?}/gm;              const attrResolver = (full, name, selected, target, label, name2, type) => {             let simpleToken = JSON.parse(JSON.stringify(token));             let charName = character.get('name');             type = ['current','max'].includes(type) ? type : 'current';             const getAttr = (n, t) => (                     findObjs({type: 'attribute', name:n, characterid: character.id})[0]                     || {get:()=>getAttrByName(character.id,n,t)}                 ).get(t);             const getFromChar = (n,t) => {                 if('name'===n){                     return charName;                 }                 return getAttr(n,t);             };             const getProp = (n, t) => {                 switch(n){                     case 'token_name':                         return simpleToken.name;                     case 'character_name':                         return charName;                     case 'bar1':                     case 'bar2':                     case 'bar3':                             return simpleToken[`${n}_${'max'===t ? 'max' : 'value'}`];                 }                 return getFromChar(n,t);             };             if(name){                 return getFromChar(name,type);             }             return getProp(name2,type);         };         return text.replace(attrRegExp, attrResolver);     };     const checkMenu = (obj,prev) => {         let to=JSON.parse(obj.get('turnorder')||'[]');         let toPrev=JSON.parse(prev.turnorder||'[]');         if(to.length && to[0].id!=='-1' && to[0].id !== (toPrev[0]||{}).id){             let token = getObj('graphic',to[0].id);             if(token && token.get('represents')){                 let character = getObj('character',token.get('represents'));                 let ability = findObjs({                     name: 'Menu',                     characterid: character.id                 }, {caseinsensitive: true})[0];                 if(ability){                     let content = resolver(token,character)(ability.get('action')).replace(/\[\[\s+/g,'[[');                     try {                         sendChat(character.get('name'),content);                     } catch(e){                         log(`Menu: ERROR PARSING: ${content}`);                         log(`Menu: ERROR: ${e}`);                     }                 }             }         }     };     on(         'change:campaign:turnorder',         (obj,prev)=>setTimeout(()=>checkMenu(Campaign(),prev),1000)     );     on('chat:message', (msg) => {         if('api'===msg.type && /^!eot\b/.test(msg.content)){             setTimeout(()=>checkMenu(Campaign(),{turnorder:JSON.stringify([{id:-1}])}),1000);         }     }); }); The specific character/ability I am looking to pull from is a character named Macros and the ability is called Menu .
1633476087
The Aaron
Roll20 Production Team
API Scripter
This is the line that gets the character:                 let character = getObj('character',token.get('represents')); You could instead use findObjs() to get the Macros character, or better yet, grab it on ready right above the function definitions. No idea on the multiple outputs.
How would that look? Code wise?
1633487622
The Aaron
Roll20 Production Team
API Scripter
Something like: let character = findObjs({type:'character',name:'Macros'})[0]; You'll want to be sure and check that character actually found something, like: if( ! character ) { return; }
I appreciate the help, but I can't get it to work lol. One of the intents is that the Menu Macro is written to track a character's current hit points status and at a certain point in Castles & Crusades you begin to bleed. I want to have that function tied into the Menu macro so when it is your turn you bleed your 1 hit point etc, but if the character is unconscious or otherwise incapacitated or the player opts to do nothing then the menu may never be triggered and they won't bleed (cheating sons of... lol).
I finally got it to work. It calls up the macro from the specific character sheet. If you want to use this you need to change the sheet (line 47) and ability (line 49) to match what you want to access. If you want the ability to be known as anything other than Menu then you need to change all refences to Menu in the code to the ability you want (find and replace works well for that). From The Aaron's original OnMyTurn script I also removed the: characterid: character.id I think the most interesting part is you could rename the ability identified in the original OnMyTurn script to different names (automaticability1, automaticability2, regeneration, etc) and as long as each one is loaded as it's own API then they can be separate abilities added to characters and not rely on someone overloading an OnMyTurn ability for multiple effects. Still can't resolve the multiple sending issue. on('ready', () => {     const resolver = (token,character) => (text) => {         const attrRegExp = /@{(?:([^|}]*)|(?:(selected)|(target)(?:\|([^|}]*))?)\|([^|}]*))(?:\|(max|current))?}/gm;              const attrResolver = (full, name, selected, target, label, name2, type) => {             let simpleToken = JSON.parse(JSON.stringify(token));             let charName = character.get('name');             type = ['current','max'].includes(type) ? type : 'current';             const getAttr = (n, t) => (                     findObjs({type: 'attribute', name:n, characterid: character.id})[0]                     || {get:()=>getAttrByName(character.id,n,t)}                 ).get(t);             const getFromChar = (n,t) => {                 if('name'===n){                     return charName;                 }                 return getAttr(n,t);             };             const getProp = (n, t) => {                 switch(n){                     case 'token_name':                         return simpleToken.name;                     case 'character_name':                         return charName;                     case 'bar1':                     case 'bar2':                     case 'bar3':                             return simpleToken[`${n}_${'max'===t ? 'max' : 'value'}`];                 }                 return getFromChar(n,t);             };             if(name){                 return getFromChar(name,type);             }             return getProp(name2,type);         };         return text.replace(attrRegExp, attrResolver);     };     const checkMenu = (obj,prev) => {         let to=JSON.parse(obj.get('turnorder')||'[]');         let toPrev=JSON.parse(prev.turnorder||'[]');         if(to.length && to[0].id!=='-1' && to[0].id !== (toPrev[0]||{}).id){             let token = getObj('graphic',to[0].id);             if(token && token.get('represents')){                 let character = findObjs({                     type:'character',                     name:' Macros '})[0];                 let ability = findObjs({                     name:' Menu ',                 }, {caseinsensitive: true})[0];                 if(ability){                     let content = resolver(token,character)(ability.get('action')).replace(/\[\[\s+/g,'[[');                     try {                         sendChat(character.get('name'),content);                     } catch(e){                         log(`Menu: ERROR PARSING: ${content}`);                         log(`Menu: ERROR: ${e}`);                     }                 }             }         }     };     on(         'change:campaign:turnorder',         (obj,prev)=>setTimeout(()=>checkMenu(Campaign(),prev),1000)     );     on('chat:message', (msg) => {         if('api'===msg.type && /^!eot\b/.test(msg.content)){             setTimeout(()=>checkMenu(Campaign(),{turnorder:JSON.stringify([{id:-1}])}),1000);         }     }); });
Now if someone could help me figure out the multiple sending to chat issue.
1633615877
The Aaron
Roll20 Production Team
API Scripter
Right!  Sorry, I'll try and duplicate that issue.  I think I can extend the original script to look for abilities that have OnMyTurn in the name, like "Reminder-concentration-OnMyTurn", then it could have multiple categorized abilities triggered. 
That would be cool. Also, menu, regeneration, etc... I do have a question, I can't get alterbars to work with it as I am trying to have it read -7 hit points (for Castles and Crusades) as bleeding and to have 1 point of damage inflicted.
1633703357

Edited 1633781797
I am trying a different modification to this API so it just sends the macro I want it to to the chat when it is the tokens turn. Of course way over my head on this. But it keeps telling me I am missing a ) after the argument. Help? on('ready', () => {     const resolver = (token,character) => (text) => {         const attrRegExp = /@{(?:([^|}]*)|(?:(selected)|(target)(?:\|([^|}]*))?)\|([^|}]*))(?:\|(max|current))?}/gm;              const attrResolver = (full, name, selected, target, label, name2, type) => {             let simpleToken = JSON.parse(JSON.stringify(token));             let charName = character.get('name');             type = ['current','max'].includes(type) ? type : 'current';             const getAttr = (n, t) => (                     findObjs({type: 'attribute', name:n, characterid: character.id})[0]                     || {get:()=>getAttrByName(character.id,n,t)}                 ).get(t);             const getFromChar = (n,t) => {                 if('name'===n){                     return charName;                 }                 return getAttr(n,t);             };             const getProp = (n, t) => {                 switch(n){                     case 'token_name':                         return simpleToken.name;                     case 'character_name':                         return charName;                     case 'bar1':                     case 'bar2':                     case 'bar3':                             return simpleToken[`${n}_${'max'===t ? 'max' : 'value'}`];                 }                 return getFromChar(n,t);             };             if(name){                 return getFromChar(name,type);             }             return getProp(name2,type);         };         return text.replace(attrRegExp, attrResolver);     };     const checkMenu = (obj,prev) => {         let to=JSON.parse(obj.get('turnorder')||'[]');         let toPrev=JSON.parse(prev.turnorder||'[]');         if(to.length && to[0].id!=='-1' && to[0].id !== (toPrev[0]||{}).id){             let token = getObj('graphic',to[0].id);             if(token && token.get('represents')){                 sendChat('menu', '/w %{Macros|Menu}')  return;                                 }         }     }     );     on(         'change:campaign:turnorder',         (obj,prev)=>setTimeout(()=>checkMenu(Campaign(),prev),1000)     );     on('chat:message', (msg) => {         if('api'===msg.type && /^!eot\b/.test(msg.content)){             setTimeout(()=>checkMenu(Campaign(),{turnorder:JSON.stringify([{id:-1}])}),1000);         }     }); });
1633706551
The Aaron
Roll20 Production Team
API Scripter
You have two too many } after the sendChat.  Take out the two right after the return;
The Aaron said: You have two too many } after the sendChat.  Take out the two right after the return; Cool. That seems to have helped. Not I need to get past the speakas issues. I really need to go back to college.
1633781848

Edited 1633927380
The Aaron said: You have two too many } after the sendChat.  Take out the two right after the return; I've changed the code above but it won't send the message. What am I missing?
1633926177
The Aaron
Roll20 Production Team
API Scripter
What do you mean by "worsened the message"?
The Aaron said: What do you mean by "worsened the message"? Won't send. Auto correct got me.