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 .
×
May your rolls be merry + bright! 🎄
Create a free account

My Macro is only working in test.

I've customed a Homebrew version of Warlock, I wanted this Macro to cause damage or heal the PC when used unfortunately I am not that skilled with making Macros so simply set it to show the damage and healing calculations. I dont know if I am messing up any where but this is sadly not working and shows #Vital Casting when I click on the Macro any where else besides the Test option. P.S if anyone skilled enough to help me I'd greatly appreciate   &{template:default} {{name=Vital Casting Use}}{{result=?{Choose Effect| Damage,?{Damage Level| Cantrip, **Cantrip Damage Vital Casting:** [[1d4]]| Level 1, **Level 1 Damage Vital Casting:** [[2d4]]| Level 2, **Level 2 Damage Vital Casting:** [[3d4]]| Level 3, **Level 3 Damage Vital Casting:** [[4d4]]| Level 4, **Level 4 Damage Vital Casting:** [[5d4]]| Level 5, **Level 5 Damage Vital Casting:** [[6d4]]| Level 6, **Level 6 Damage Vital Casting:** [[7d4]] }| Healing (on kill only),?{Healing Level| Cancel, | Level 5, **Level 5 Healing Vital Casting:** [[1d4+5]]| Level 8, **Level 8 Healing Vital Casting:** [[1d4+8]]| Level 11, **Level 11 Healing Vital Casting:** [[2d4+11]]| Level 13, **Level 13 Healing Vital Casting:** [[2d4+13]]| Level 15, **Level 15 Healing Vital Casting:** [[3d4+15]] } }}
You cannot have any spaces in macro names. You can change the macro name to "VitalCasting" or " Vital_Casting" or " Vital-Casting" and it will work. (To call the macro add the hashtag in front, e.g. #VitalCasting.)
Gotcha thats great to know thank you ill try it out and let you know the results!
You're a Gods send thank you! Sorry to sound needy but can I tie this macro to effect a character sheet? Ill try to figure it out if I can just need to know if its possible
1766275561
timmaugh
Forum Champion
API Scripter
On their own, macros cannot alter a character sheet. However, scripts can... and there are scripts that can fire from *within* this message, and/or there are scripts that can package up this message with a second, script-based message (so that they can read the same data). If this character is using the 2024 sheet, however, that option may not work because script integration with that sheet isn't available yet.
Understood thanks. Ill leave it as is for now until more options become available.
Gluttonous Gazer said: You're a Gods send thank you! Sorry to sound needy but can I tie this macro to effect a character sheet? Ill try to figure it out if I can just need to know if its possible It really depends on what you want to do. A macro can reference attributes from a selected token that is linked to a character sheet, but it cannot make any modifications unless it uses a Mod (API) script command. Without a Pro/Elite subscription, all chat commands (including macros) are “read-only”. 
Its more trying to make the Script damage/heal the PC when used. I think i've made the Script but again im sorta just bumbling along and hoping it works on('ready', () => {   log('Vital-Casting (Sterling Burrow Only) Ready'); }); /* =========================    CONFIG — CHANGE NAME IF NEEDED ========================= */ const CHARACTER_NAME = 'Sterling Burrow'; /* =========================    DICE TABLES ========================= */ const DAMAGE_TABLE = {   cantrip: '1d4',   1: '2d4',   2: '3d4',   3: '4d4',   4: '5d4',   5: '6d4',   6: '7d4' }; const HEAL_TABLE = {   5: '1d4+1',   8: '1d4+3',   11: '2d4+5',   13: '2d4+7',   15: '3d4+9' }; /* =========================    MAIN HANDLER ========================= */ on('chat:message', msg => {   if (msg.type !== 'api') return;   if (!msg.content.startsWith('!vital-casting')) return;   // Get character by name ONLY   const character = findObjs({     _type: 'character',     name: CHARACTER_NAME   })[0];   if (!character) {     sendChat('System', `/w gm Character "${CHARACTER_NAME}" not found.`);     return;   }   const args = msg.content.split(' ');   const effect = args[1]; // damage | heal   const level = args[2];   const hp = findObjs({     _type: 'attribute',     characterid: character.id,     name: 'hp'   })[0];   const hpMax = findObjs({     _type: 'attribute',     characterid: character.id,     name: 'hp_max'   })[0];   if (!hp || !hpMax) {     sendChat('System', '/w gm HP attributes not found.');     return;   }   const formula =     effect === 'damage'       ? DAMAGE_TABLE[level]       : HEAL_TABLE[level];   if (!formula) {     sendChat('System', '/w gm Invalid Vital-Casting option.');     return;   }   sendChat('Vital-Casting', `/roll ${formula}`, rolls => {     const roll = JSON.parse(rolls[0].content);     const amount = roll.total;     let currentHP = parseInt(hp.get('current'), 10);     const maxHP = parseInt(hpMax.get('current'), 10);     if (effect === 'damage') {       currentHP = Math.max(0, currentHP - amount);     } else {       currentHP = Math.min(maxHP, currentHP + amount);     }     hp.set('current', currentHP);     sendChat(       character.get('name'),       `&{template:default}       {{name=Vital-Casting}}       {{Effect=${effect.toUpperCase()}}}       {{Amount=${amount}}}       {{HP=${currentHP}/${maxHP}}}`     );   }); });
1766292585

Edited 1766292634
Andrew R.
Pro
Sheet Author
You don't want to be writing something like this in JavaScript. The Mods you should look into are TokenMod (which changes everything to do with tokens), CharSetAttr (which changes everything to do with character sheets except D&D 2024), and ScriptCards (which is a general programming language useful widely).  I use ScriptCards & TokenMod all the time .
That sounds awesome only thing im cautious about is never using them took me months to figure out java lol. Ill try it out tho hopefully nothing burns down.
1766333839
timmaugh
Forum Champion
API Scripter
If this is your first foray into scripts, Gluttonous Gazer, then welcome! I agree with Andrew R. that you should look to existing mods -- because for something like this someone, somewhere very likely had the same need, and you can simplify the amount of work for yourself and save your development efforts for something that hasn't received any attention -- ...unless... ...you're looking to learn coding in the Roll20 scriptosphere. Then something like this is straightforward enough to provide opportunity to get your feet wet without being too complex, especially if you're also just learning JavaScript. If that's your goal (learning), then I should point out a couple of things... Your script reads fine, and will likely work. Nothing jumps out at me as far as missed conditional paths or bad syntax. However, all of the scripts in your game get rolled up into a single, long file of javascript before being "read" into the interface. That means all scripts in a game exist in the same global namespace, and can overwrite previous declarations if the naming is the same; the implication is that everything in your script not otherwise scoped to a closure (function, object, code block, etc.) is in danger of getting stepped on by other code, later, and that kind of an issue would be very hard to diagnose and troubleshoot. For you, that's your declaration of: CHARACTER_NAME DAMAGE_TABLE ...and... HEAL_TABLE = { You *did* declare these with the  const  keyword, so you'll at least get an error if some other script tries to redeclare them in the global namespace, but you can prevent against that just by giving them their own scope/closure that will survive (as you need these values to continue to exist so you can reference them in your command processing). The fix for that is actually the fix for my second point, too, so let me state that before I get to the solution: the other thing to keep in mind is the way you register a script to listen for a Roll20 event (like a chat message). The way you've done it will work, but you do limit your script's ability to have its capabilities enhanced by metascripts. If you don't know what metascripts are, don't worry -- much like normal scripts, you don't have to use them; they're just handy to be able to bring to bear when you need them. And since, like I said, the fix to allow metascript augmentation is the same fix that will save against namespace pollution and competition, you'll get both benefits just by adjusting your code slightly. The fix is just to put your global declarations in your on('ready') event AS WELL AS putting your on('chat:message') event in the on('ready') event, too. This will 1) delay the registration of the chat listener until the game's "ready" event is fired (allowing for metascript integration), and 2) keep the on('ready') closure available for the chat handler to access those global variables while 3) protecting against namespace pollution. The resulting shape of the script is more like: on('ready', () => {   // global variables go here...   const CHARACTER_NAME = 'Actual Cannibal';   // ...etc...   on('chat:message', msg => {     // chat handling goes here...     if (msg.type !== 'api') return;     if (!msg.content.startsWith('!vital-casting')) return;     // ...etc...   }); });
I think im starting to understand so something more like this? on('ready', () => {   'use strict';   log('Vital-Casting (Sterling Burrow Only) Ready');   /* =========================      CONFIG   ========================= */   const CHARACTER_NAME = 'Sterling Burrow';   /* =========================      DICE TABLES   ========================= */   const DAMAGE_TABLE = {     cantrip: '1d4',     1: '2d4',     2: '3d4',     3: '4d4',     4: '5d4',     5: '6d4',     6: '7d4'   };   const HEAL_TABLE = {     5: '1d4+1',     8: '1d4+3',     11: '2d4+5',     13: '2d4+7',     15: '3d4+9'   };   /* =========================      CHAT HANDLER   ========================= */   on('chat:message', msg => {     if (msg.type !== 'api') return;     if (!msg.content.startsWith('!vital-casting')) return;     const [, effect, level] = msg.content.split(/\s+/);     if (!['damage', 'heal'].includes(effect)) {       sendChat('Vital-Casting', '/w gm Invalid effect. Use "damage" or "heal".');       return;     }     const character = findObjs({       _type: 'character',       name: CHARACTER_NAME     })[0];     if (!character) {       sendChat('Vital-Casting', `/w gm Character "${CHARACTER_NAME}" not found.`);       return;     }     const hp = findObjs({       _type: 'attribute',       characterid: character.id,       name: 'hp'     })[0];     const hpMax = findObjs({       _type: 'attribute',       characterid: character.id,       name: 'hp_max'     })[0];     if (!hp || !hpMax) {       sendChat('Vital-Casting', '/w gm HP attributes not found.');       return;     }     const formula =       effect === 'damage'         ? DAMAGE_TABLE[level]         : HEAL_TABLE[level];     if (!formula) {       sendChat(         'Vital-Casting',         `/w gm Invalid level "${level}" for ${effect}.`       );       return;     }     sendChat('Vital-Casting', `/roll ${formula}`, rolls => {       const rollData = JSON.parse(rolls[0].content);       const amount = rollData.total;       let currentHP = parseInt(hp.get('current'), 10);       const maxHP = parseInt(hpMax.get('current'), 10);       if (effect === 'damage') {         currentHP = Math.max(0, currentHP - amount);       } else {         currentHP = Math.min(maxHP, currentHP + amount);       }       hp.set('current', currentHP);       sendChat(         character.get('name'),         [           '&{template:default}',           '{{name=Vital Casting}}',           `{{Effect=${effect === 'damage' ? 'Damage Taken' : 'Healing Received'}}}`,           `{{Roll=${formula}}}`,           `{{Result=${amount}}}`,           `{{HP=${currentHP} / ${maxHP}}}`         ].join('\n')       );     });   }); });
1766341339
timmaugh
Forum Champion
API Scripter
That's it!
Thanks xD <3