It's not the command. It works fine via macro and direct entry in chat, copied and pasted from the script arg. I must be missing something in the arg or opt that is preventing it from firing. I have the same problem with the remove token option as well. The output runs correctly, but the argument is not applied in either the <delstatus> or <concen> arguments. Here is the entire altered script as I have it running now: /* global log, _, getObj, HealthColors, playerIsGM, sendChat, on, libTokenMarkers */ const ApplyDamage = (() => { const version = "1.2"; const observers = { "change": [] }; let boundedBar = false; const defaultOpts = { type: "half", ids: "", saves: "", DC: "-1", dmg: "0", bar: "1" }; const checkInstall = () => { log(`-=> ApplyDamage v${version} <=-`); if('undefined' === typeof libTokenMarkers || (['getStatus','getStatuses','getOrderedList'].find(k=> !libTokenMarkers.hasOwnProperty(k) || 'function' !== typeof libTokenMarkers[k] )) ) { // notify of the missing library sendChat('',`/w gm <div style="color:red;font-weight:bold;border:2px solid red;background-color:black;border-radius:1em;padding:1em;">Missing dependency: libTokenMarkers</div>`); } }; const getWhisperPrefix = (playerid) => { const player = getObj("player", playerid); if (player && player.get("_displayname")) { return `/w "${player.get("_displayname")}" `; } else { return "/w GM "; } }; const parseOpts = (content, hasValue) => { return content .replace(/<br\/>\n/g, " ") .replace(/({{(.*?)\s*}}\s*$)/g, "$2") .split(/\s+--/) .slice(1) .reduce((opts, arg) => { const kv = arg.split(/\s(.+)/); if (hasValue.includes(kv[0])) { opts[kv[0]] = (kv[1] || ""); } else { opts[arg] = true; } return opts; }, {}); }; const processInlinerolls = function (msg) { if (msg.inlinerolls && msg.inlinerolls.length) { return msg.inlinerolls.map(v => { const ti = v.results.rolls.filter(v2 => v2.table) .map(v2 => v2.results.map(v3 => v3.tableItem.name).join(", ")) .join(", "); return (ti.length && ti) || v.results.total || 0; }).reduce((m, v, k) => m.replace(`$[[${k}]]`, v), msg.content); } else { return msg.content; } }; const handleError = (whisper, errorMsg) => { const output = `${whisper}<div style="border:1px solid black;background:#FFBABA;padding:3px">` + `<h4>Error</h4><p>${errorMsg}</p></div>`; sendChat("ApplyDamage", output); }; const finalApply = (results, dmg, type, bar, status, delstatus, concen,) => { const barCur = `bar${bar}_value`, barMax = `bar${bar}_max`; Object.entries(results).forEach(([id, saved]) => { const token = getObj("graphic", id), prev = JSON.parse(JSON.stringify(token || {})); let newValue; if (token && !saved) { if (boundedBar) { newValue = Math.min(Math.max(parseInt(token.get(barCur)) - dmg, 0), parseInt(token.get(barMax))); } else { newValue = parseInt(token.get(barCur)) - dmg; } if (status) { let tm = libTokenMarkers.getStatus(status); token.set(`status_${tm.getTag()}`, true); } if (delstatus) { let tm = libTokenMarkers.getStatus(status); token.set(`status_${tm.getTag()}`, false); } if (concen) { sendChat('',"!cmaster --remove,condition=concentration"); return}; } else if (token && type === "half") { if (boundedBar) { newValue = Math.min(Math.max(parseInt(token.get(barCur)) - Math.floor(dmg / 2), 0), parseInt(token.get(barMax))); } else { newValue = parseInt(token.get(barCur)) - Math.floor(dmg / 2); } } if (!_.isUndefined(newValue)) { if (Number.isNaN(newValue)) newValue = token.get(barCur); token.set(barCur, newValue); notifyObservers("change", token, prev); } }); }; const handleInput = (msg) => { if (msg.type === "api" && msg.content.search(/^!apply-damage\b/) !== -1) { const hasValue = ["ids", "saves", "DC", "type", "dmg", "bar", "status","delstatus"], opts = Object.assign({}, defaultOpts, parseOpts(processInlinerolls(msg), hasValue)); opts.ids = opts.ids.split(/,\s*/g); opts.saves = opts.saves.split(/,\s*/g); opts.DC = parseInt(opts.DC); opts.dmg = parseInt(opts.dmg); if (!playerIsGM(msg.playerid) && getObj("player", msg.playerid)) { handleError(getWhisperPrefix(msg.playerid), "Permission denied."); return; } if (!["1", "2", "3"].includes(opts.bar)) { handleError(getWhisperPrefix(msg.playerid), "Invalid bar."); return; } if (opts.status === "none") { delete opts.status; } if (opts.delstatus === "none") { delete opts.delstatus; } if (opts.concen === "none") { delete opts.concen; } if (opts.status && 0 === libTokenMarkers.getStatuses(opts.status).length) { handleError(getWhisperPrefix(msg.playerid), "Invalid status."); return; } if (opts.delstatus && 0 === libTokenMarkers.getStatuses(opts.delstatus).length) { handleError(getWhisperPrefix(msg.playerid), "Invalid status."); return; } const results = _.reduce(opts.ids, function (m, id, k) { m[id] = parseInt(opts.saves[k] || "0") >= opts.DC; return m; }, {}); finalApply(results, opts.dmg, opts.type, opts.bar, opts.status, opts.delstatus); const output = `${ getWhisperPrefix(msg.playerid) }<div style="border:1px solid black;background:#FFF;padding:3px"><p>${ (opts.dmg ? `${opts.dmg} damage applied to tokens, with ${ (opts.type === "half" ? "half" : "no") } damage on a successful saving throw.` : "")}${ (opts.status ? ` ${opts.status} status marker applied to tokens that failed the save.` : "")}${ (opts.delstatus ? ` ${opts.delstatus} status marker removed from tokens that failed the save.` : "")}${ (opts.concen ? ` Concentration status marker removed from tokens that failed the save.` : "") }</p></div>`; sendChat("ApplyDamage", output, null, { noarchive: true }); } return; }; const notifyObservers = (event, obj, prev) => { observers[event].forEach(observer => observer(obj, prev)); }; const registerObserver = (event, observer) => { if (observer && _.isFunction(observer) && observers.hasOwnProperty(event)) { observers[event].push(observer); } else { log("ApplyDamage event registration unsuccessful."); } }; const registerEventHandlers = () => { on("chat:message", handleInput); }; on("ready", () => { checkInstall(); registerEventHandlers(); if ("undefined" !== typeof HealthColors) { ApplyDamage.registerObserver("change", HealthColors.Update); } }); return { registerObserver }; })();