Hey folks, I'm having trouble with a script for spawning custom FX alongside the base attack roll. The idea is that each weapon in the repeating section has a linked FX, usually custom, so you have to go through a rigamarole to make the right FX spawn on command. I've actually solved this issue in the past her e, but now it's giving me trouble with what should be a simpler script. The crash tells me "name" is undefined, but my logs tell me "name" is being found accurately. All of the args look like exactly what I need the script to find. I'm seeing a lot of variance as to where my logs stop. It often stops after logging "name" and "main," but sometimes it gets past the token name and "dr". Either way, I'm not sure what I'm doing wrong, because I thought I just copied a script that was already working. Here's the button command and script: “!fxattack2 --@{character_id} --@{target|character_id} --{weapon} --@{damagedie} --@{weaponfx} --@{selected|token_id} --@{target|token_id}" // wait till the ready event before registering a chat handler on('ready', () => { // create a function to return attribute value, given character id and attribute name. const getLocation = function(id, choice) { let location = parseInt((findObjs({ type: 'attribute', characterid: id, name: choice })[0] || { get: () => -1 }).get('current')); return location; }; on('chat:message', (msg) => { if ('api' === msg.type && /^!fxattack2\b/i.test(msg.content)) { const args = msg.content.split(/\s+--/); log(args); let c = getObj('character',args[1]); log(c); // verify we got a character if(c){ let name = getAttrByName(c.id, "character_name"); let main = getAttrByName(c.id, "main"); let ar = getAttrByName(c.id, "ar"); log(name); log(main); log(ar); } let t = getObj('character',args[2]); if (t) { let tname = getAttrByName(t.id, "character_name"); let dr = getAttrByName(t.id, "dr"); let av = getAttrByName(t.id, "av"); log(tname); log(dr); log(av); } const weapon = args[3] ; const damagedie = args[4]; const fx = args[5]; log(fx); const ctoken = args[6]; const ttoken = args[7]; let fxid = findObjs({_type: "custfx", name: fx})[0].id; log(fxid); const tokenCenter = (id) => { const token = getObj('graphic', id); log(token); return { x: Math.round(token.get('left')), y: Math.round(token.get('top')) } }; log(tokenCenter); let output = `?{Roll Type| Standard, 2d10m| Benefit, 3d10k2m| Hindrance, 3d10dh1m} &{template:default} {{name= ${name}: ${weapon} Attack }} {{STATS= ${main} ${ar} | Bonus ?{Core Path Points| 0} }} {{TARGET= ${tname} | DR ${dr} | AV ${av} }} {{RESULT= [[?{Roll Type} + ${ar} + ?{Core Path Points| 0}]] }} {{DAMAGE= [[${damagedie}+ ${ar} - ${av}]] }}`; sendChat('', output); if (fx == "sword" ||fx == "melee" ||fx == "hammer" ||fx == "stab") { let p = tokenCenter(ttoken); spawnFx(p.x, p.y, fxid) } else { spawnFxBetweenPoints(tokenCenter(ctoken), tokenCenter(ttoken), fxid); log(tokenCenter(ttoken)); } } }); });