The Aaron said: I'd have to look at the CFX script, but probably it does something like checks if a player is a gm, which would fail if it gets called from a script. Here is the script I have installed: on('ready',()=>{ const isBuiltinFx = (name) => /(beam|bomb|breath|bubbling|burn|burst|explode|glow|missile|nova|splatter)-(acid|blood|charm|death|fire|frost|holy|magic|slime|smoke|water)/.test(name); const getPageForPlayer = (playerid) => { let player = getObj('player',playerid); if(playerIsGM(playerid)){ return player.get('lastpage'); } let psp = Campaign().get('playerspecificpages'); if(psp[playerid]){ return psp[playerid]; } return Campaign().get('playerpageid'); }; on('chat:message',(msg)=>{ if('api' !== msg.type ) { return; } let args = msg.content.split(/\s+/); switch(args.shift().toLowerCase()){ case '!cfx': { if (args.length < 3){ sendChat("CFX", `/w "${who}" Use <code>!cfx [effect] [source id] [destination id ...]</code><br><code>id</code>s can be token or character ids. You can specify as many destination ids as you like to target multiple tokens or creatures.`); return; } let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); let srcToken = getObj('graphic',args[1]); let pageid = getPageForPlayer(msg.playerid); if(!srcToken) { let character = getObj('character',args[1]); if(character){ let ts = findObjs({ type: 'graphic', represents: character.id, pageid: pageid }); if(ts.length){ srcToken = ts[0]; } } } let destTokens = args.slice(2) .map((id)=>getObj('graphic',id) || findObjs({type:'graphic', represents:id, pageid})) .reduce((m,o)=>[...m,...(Array.isArray(o) ? o : [o])],[]) ; if(!srcToken){ sendChat("CFX", `/w "${who}" No matching tokens source character or token ID on your current page.`); return; } if(0 === destTokens.length){ sendChat("CFX", `/w "${who}" No destination tokens found for supplied IDs.`); return; } let srcPt = { x: srcToken.get('left'), y: srcToken.get('top') }; let targeted = false; let effect = args[0]; if(!isBuiltinFx(effect)){ let custfx = findObjs({type: 'custfx', name: effect}, {caseInsensitive: true})[0]; if(!custfx){ sendChat("CFX", `/w "${who}" Not a built in or custom effect: <code>${effect}</code>`); return; } targeted = (-1 === parseInt((custfx.get('definition')||{}).angle)); effect = custfx.id; } else { targeted = /^(beam|breath|splatter)-/.test(effect); } let spawner = targeted ? (s,d,e,p) => spawnFxBetweenPoints(s,d,e,p) : (s,d,e,p) => spawnFx(d.x,d.y,e,p) ; destTokens.forEach((t)=>{ let destPt = { x: t.get('left'), y: t.get('top') }; spawner(srcPt,destPt,effect,t.get('pageid')); }); } break; } }); log("-=> CFX command loaded (!cfx) <=-"); });