6 lines
48 KiB
Plaintext
6 lines
48 KiB
Plaintext
{"name":"Active Aura Only (Generic)","type":"script","img":"icons/svg/dice-target.svg","scope":"global","command":"if(!game.modules.get(\"ActiveAuras\")?.active) {\n ui.notifications.error(\"ActiveAuras is not enabled\");\n return;\n}\n\nconst lastArg = args[args.length - 1];\n\nasync function wait(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); }\n\nasync function attemptRemoval(targetToken, condition, item) {\n if (game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n new Dialog({\n title: `Use action to attempt to remove ${condition}?`,\n buttons: {\n one: {\n label: \"Yes\",\n callback: async () => {\n const caster = item.parent;\n const saveDc = caster.system.attributes.spelldc;\n const removalCheck = item.flags.ddbimporter.effect.removalCheck;\n const removalSave = item.flags.ddbimporter.effect.removalSave;\n const ability = removalCheck ? removalCheck : removalSave;\n const type = removalCheck ? \"check\" : \"save\";\n const flavor = `${condition} (via ${item.name}) : ${CONFIG.DND5E.abilities[ability]} ${type} vs DC${saveDc}`;\n const rollResult = removalCheck\n ? (await targetToken.actor.rollAbilityTest(ability, { flavor })).total\n : (await targetToken.actor.rollAbilitySave(ability, { flavor })).total;\n\n if (rollResult >= saveDc) {\n game.dfreds.effectInterface.removeEffect({ effectName: condition, uuid: targetToken.document.uuid });\n } else {\n if (rollResult < saveDc) ChatMessage.create({ content: `${targetToken.name} fails the ${type} for ${item.name}, still has the ${condition} condition.` });\n }\n },\n },\n two: {\n label: \"No\",\n callback: () => {},\n },\n },\n }).render(true);\n }\n}\n\nasync function applyCondition(condition, targetToken, item, itemLevel) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n const caster = item.parent;\n const workflowItemData = duplicate(item.data);\n workflowItemData.system.target = { value: 1, units: \"\", type: \"creature\" };\n workflowItemData.system.save.ability = item.flags.ddbimporter.effect.save;\n workflowItemData.system.components.concentration = false;\n workflowItemData.system.level = itemLevel;\n workflowItemData.system.duration = { value: null, units: \"inst\" };\n workflowItemData.system.target = { value: null, width: null, units: \"\", type: \"creature\" };\n workflowItemData.system.preparation.mode = \"atwill\";\n setProperty(workflowItemData, \"flags.itemacro\", {});\n setProperty(workflowItemData, \"flags.midi-qol\", {});\n setProperty(workflowItemData, \"flags.dae\", {});\n setProperty(workflowItemData, \"effects\", []);\n delete workflowItemData._id;\n workflowItemData.name = `${workflowItemData.name}: ${item.name} Condition save`;\n // console.warn(\"workflowItemData\", workflowItemData);\n\n const saveTargets = [...game.user?.targets].map((t )=> t.id);\n game.user.updateTokenTargets([targetToken.id]);\n const saveItem = new CONFIG.Item.documentClass(workflowItemData, { parent: caster });\n const options = { showFullCard: false, createWorkflow: true, configureDialog: true };\n const result = await MidiQOL.completeItemRoll(saveItem, options);\n\n game.user.updateTokenTargets(saveTargets);\n const failedSaves = [...result.failedSaves];\n if (failedSaves.length > 0) {\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: failedSaves[0].document.uuid });\n }\n\n return result;\n }\n}\n\nasync function attachSequencerFileToTemplate(templateUuid, sequencerFile, originUuid) {\n if (game.modules.get(\"sequencer\")?.active) {\n if (Sequencer.Database.entryExists(sequencerFile)) {\n console.debug(`Trying to apply sequencer effect (${sequencerFile}) to ${templateUuid} from ${originUuid}`, sequencerFile);\n const template = await fromUuid(templateUuid);\n new Sequence()\n .effect()\n .file(Sequencer.Database.entryExists(sequencerFile))\n .size({\n width: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n height: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n })\n .persist(true)\n .origin(originUuid)\n .belowTokens()\n .opacity(0.5)\n .attachTo(template, { followRotation: true })\n .stretchTo(template, { attachTo: true})\n .play();\n }\n }\n}\n\nif (args[0].tag === \"OnUse\" && args[0].macroPass === \"preActiveEffects\") {\n const safeName = lastArg.itemData.name.replace(/\\s|'|\\.|’/g, \"_\");\n const dataTracker = {\n randomId: randomID(),\n targetUuids: lastArg.targetUuids,\n startRound: game.combat.round,\n startTurn: game.combat.turn,\n spellLevel: lastArg.spellLevel,\n };\n\n const item = await fromUuid(lastArg.itemUuid);\n // await item.update(dataTracker);\n await DAE.unsetFlag(item, `${safeName}Tracker`);\n await DAE.setFlag(item, `${safeName}Tracker`, dataTracker);\n\n const sequencerFile = lastArg.item.flags.ddbimporter?.effect?.sequencerFile;\n if (sequencerFile) {\n attachSequencerFileToTemplate(lastArg.templateUuid, sequencerFile, lastArg.itemUuid)\n }\n\n if (lastArg.item.flags.ddbimporter?.effect?.applyImmediate) {\n await wait(500);\n const condition = lastArg.item.flags.ddbimporter.effect.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n\n return await AAhelpers.applyTemplate(args);\n\n} else if (args[0].tag === \"OnUse\" && args[0].macroPass === \"postActiveEffects\") {\n if (lastArg.item.flags.ddbimporter?.effect?.applyImmediate) {\n const condition = lastArg.item.flags.ddbimporter.effect.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n} else if (args[0] == \"on\" || args[0] == \"each\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const item = await fromUuid(lastArg.efData.origin);\n // sometimes the round info has not updated, so we pause a bit\n if (args[0] == \"each\") await wait(500);\n const targetItemTracker = DAE.getFlag(item.parent, `${safeName}Tracker`);\n const originalTarget = targetItemTracker.targetUuids.includes(lastArg.tokenUuid);\n const target = canvas.tokens.get(lastArg.tokenId);\n const targetTokenTrackerFlag = DAE.getFlag(target, `${safeName}Tracker`);\n const targetedThisCombat = targetTokenTrackerFlag && targetItemTracker.randomId === targetTokenTrackerFlag.randomId;\n const targetTokenTracker = targetedThisCombat\n ? targetTokenTrackerFlag\n : {\n randomId: targetItemTracker.randomId,\n round: game.combat.round,\n turn: game.combat.turn,\n hasLeft: false,\n condition: item.flags.ddbimporter.effect.condition,\n };\n\n const castTurn = targetItemTracker.startRound === game.combat.round && targetItemTracker.startTurn === game.combat.turn;\n const isLaterTurn = game.combat.round > targetTokenTracker.round || game.combat.turn > targetTokenTracker.turn;\n const everyEntry = hasProperty(item.data, \"flags.ddbimporter.effect.everyEntry\")\n ? item.flags.ddbimporter.effect.everyEntry\n : false;\n\n // if:\n // not cast turn, and not part of the original target\n // AND one of the following\n // not original template and have not yet had this effect applied this combat OR\n // has been targeted this combat, left and re-entered effect, and is a later turn\n\n if (castTurn && originalTarget) {\n console.debug(`Token ${target.name} is part of the original target for ${item.name}`);\n } else if (everyEntry || !targetedThisCombat || (targetedThisCombat && isLaterTurn)) {\n console.debug(`Token ${target.name} is targeted for immediate save vs condition with ${item.name}, using the following factors`, { originalTarget, castTurn, targetedThisCombat, targetTokenTracker, isLaterTurn });\n targetTokenTracker.hasLeft = false;\n await applyCondition(targetTokenTracker.condition, target, item, targetItemTracker.spellLevel);\n }\n await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);\n const allowVsRemoveCondition = item.flags.ddbimporter.effect.allowVsRemoveCondition;\n const effectApplied = game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, target.document.uuid);\n const currentTokenCombatTurn = game.combat.current.tokenId === lastArg.tokenId;\n if (currentTokenCombatTurn && allowVsRemoveCondition && effectApplied) {\n console.warn(`Removing ${targetTokenTracker.condition}`);\n await attemptRemoval(target, targetTokenTracker.condition, item);\n }\n} else if (args[0] == \"off\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const targetToken = await fromUuid(lastArg.tokenUuid);\n const targetTokenTracker = await DAE.getFlag(targetToken, `${safeName}Tracker`);\n const removeOnOff = hasProperty(lastArg, \"efData.flags.ddbimporter.effect.removeOnOff\")\n ? lastArg.efData.flags.ddbimporter.effect.removeOnOff\n : true;\n\n if (targetTokenTracker?.condition && removeOnOff && game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, lastArg.tokenUuid)) {\n console.debug(`Removing ${targetTokenTracker.condition} from ${targetToken.name}`);\n game.dfreds.effectInterface.removeEffect({ effectName: targetTokenTracker.condition, uuid: lastArg.tokenUuid });\n }\n\n if (targetTokenTracker) {\n targetTokenTracker.hasLeft = true;\n targetTokenTracker.turn = game.combat.turn;\n targetTokenTracker.round = game.combat.round;\n await DAE.setFlag(targetToken, `${safeName}Tracker`, targetTokenTracker);\n }\n}","folder":"Xnvpa6bGFYi4yoqK","flags":{"advanced-macros":{"runAsGM":false}},"author":"xOFiqDVDAkPwiqtI","sort":0,"ownership":{"default":0,"xOFiqDVDAkPwiqtI":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.291","createdTime":1672646160256,"modifiedTime":1672646160256,"lastModifiedBy":"xOFiqDVDAkPwiqtI"},"_id":"8ewUgzM0IbTcfc2J"}
|
||
{"name":"Active Aura Damage On Entry (Generic)","type":"script","img":"icons/svg/dice-target.svg","scope":"global","command":"if(!game.modules.get(\"ActiveAuras\")?.active) {\n ui.notifications.error(\"ActiveAuras is not enabled\");\n return;\n}\n\nconsole.warn(args)\n\nconst lastArg = args[args.length - 1];\n\nfunction getCantripDice(actor) {\n const level = actor.type === \"character\" ? actor.system.details.level : actor.system.details.cr;\n return 1 + Math.floor((level + 1) / 6);\n}\n\nasync function rollItemDamage(targetToken, itemUuid, itemLevel) {\n const item = await fromUuid(itemUuid);\n const caster = item.parent;\n const ddbEffectFlags = item.flags.ddbimporter.effect;\n const isCantrip = ddbEffectFlags.isCantrip;\n const damageDice = ddbEffectFlags.dice;\n const damageType = ddbEffectFlags.damageType;\n const saveAbility = ddbEffectFlags.save;\n const casterToken = canvas.tokens.placeables.find((t) => t.actor?.uuid === caster.uuid);\n const scalingDiceArray = item.system.scaling.formula.split(\"d\");\n const scalingDiceNumber = itemLevel - item.system.level;\n const upscaledDamage = isCantrip\n ? `${getCantripDice(caster.data)}d${scalingDiceArray[1]}[${damageType}]`\n : scalingDiceNumber > 0 ? `${scalingDiceNumber}d${scalingDiceArray[1]}[${damageType}] + ${damageDice}` : damageDice;\n\n const workflowItemData = duplicate(item.data);\n workflowItemData.system.target = { value: 1, units: \"\", type: \"creature\" };\n workflowItemData.system.save.ability = saveAbility;\n workflowItemData.system.components.concentration = false;\n workflowItemData.system.level = itemLevel;\n workflowItemData.system.duration = { value: null, units: \"inst\" };\n workflowItemData.system.target = { value: null, width: null, units: \"\", type: \"creature\" };\n\n setProperty(workflowItemData, \"flags.itemacro\", {});\n setProperty(workflowItemData, \"flags.midi-qol\", {});\n setProperty(workflowItemData, \"flags.dae\", {});\n setProperty(workflowItemData, \"effects\", []);\n delete workflowItemData._id;\n\n const saveOnEntry = ddbEffectFlags.saveOnEntry;\n console.warn(\"saveOnEntry\", {ddbEffectFlags, saveOnEntry});\n if (saveOnEntry) {\n const entryItem = new CONFIG.Item.documentClass(workflowItemData, { parent: caster });\n console.warn(\"Saving item on entry\", {entryItem, targetToken});\n const options = {\n showFullCard: false,\n createWorkflow: true,\n targetUuids: [targetToken.document.uuid],\n configureDialog: false,\n versatile: false,\n consumeResource: false,\n consumeSlot: false,\n };\n await MidiQOL.completeItemRoll(entryItem, options);\n } else {\n const damageRoll = await new Roll(upscaledDamage).evaluate({ async: true });\n if (game.dice3d) game.dice3d.showForRoll(damageRoll);\n\n workflowItemData.name = `${workflowItemData.name}: Turn Entry Damage`;\n // console.warn(\"workflowItemData\", workflowItemData);\n\n await new MidiQOL.DamageOnlyWorkflow(\n caster,\n casterToken,\n damageRoll.total,\n damageType,\n [targetToken],\n damageRoll,\n {\n flavor: `(${CONFIG.DND5E.damageTypes[damageType]})`,\n itemCardId: \"new\",\n itemData: workflowItemData,\n isCritical: false,\n }\n );\n }\n\n}\n\nasync function attachSequencerFileToTemplate(templateUuid, sequencerFile, originUuid) {\n if (game.modules.get(\"sequencer\")?.active) {\n if (Sequencer.Database.entryExists(sequencerFile)) {\n console.debug(\"Trying to apply sequencer effect\", {sequencerFile, templateUuid});\n const template = await fromUuid(templateUuid);\n new Sequence()\n .effect()\n .file(Sequencer.Database.entryExists(sequencerFile))\n .size({\n width: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n height: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n })\n .persist(true)\n .origin(originUuid)\n .belowTokens()\n .opacity(0.5)\n .attachTo(template, { followRotation: true })\n .stretchTo(template, { attachTo: true})\n .play();\n }\n }\n}\n\nif (args[0].tag === \"OnUse\" && args[0].macroPass === \"preActiveEffects\") {\n const safeName = lastArg.itemData.name.replace(/\\s|'|\\.|’/g, \"_\");\n const dataTracker = {\n randomId: randomID(),\n targetUuids: lastArg.targetUuids,\n startRound: game.combat.round,\n startTurn: game.combat.turn,\n spellLevel: lastArg.spellLevel,\n };\n\n const item = await fromUuid(lastArg.itemUuid);\n await DAE.unsetFlag(item, `${safeName}Tracker`);\n await DAE.setFlag(item, `${safeName}Tracker`, dataTracker);\n\n const ddbEffectFlags = lastArg.item.flags.ddbimporter?.effect;\n\n if (ddbEffectFlags) {\n const sequencerFile = ddbEffectFlags.sequencerFile;\n if (sequencerFile) {\n attachSequencerFileToTemplate(lastArg.templateUuid, sequencerFile, lastArg.itemUuid)\n }\n if (ddbEffectFlags.isCantrip) {\n const cantripDice = getCantripDice(lastArg.actor);\n args[0].spellLevel = cantripDice;\n ddbEffectFlags.cantripDice = cantripDice;\n let newEffects = args[0].item.effects.map((effect) => {\n effect.changes = effect.changes.map((change) => {\n change.value = change.value.replace(\"@cantripDice\", cantripDice)\n return change;\n });\n return effect;\n });\n args[0].item.effects = duplicate(newEffects);\n args[0].itemData.effects = duplicate(newEffects);\n }\n const template = await fromUuid(lastArg.templateUuid);\n await template.update({\"flags.effect\": ddbEffectFlags});\n }\n\n return await AAhelpers.applyTemplate(args);\n\n} else if (args[0] == \"on\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const item = await fromUuid(lastArg.efData.origin);\n const targetItemTracker = DAE.getFlag(item.parent, `${safeName}Tracker`);\n const originalTarget = targetItemTracker.targetUuids.includes(lastArg.tokenUuid);\n const target = canvas.tokens.get(lastArg.tokenId);\n const targetTokenTrackerFlag = DAE.getFlag(target, `${safeName}Tracker`);\n const targetedThisCombat = targetTokenTrackerFlag && targetItemTracker.randomId === targetTokenTrackerFlag.randomId;\n const targetTokenTracker = targetedThisCombat\n ? targetTokenTrackerFlag\n : {\n randomId: targetItemTracker.randomId,\n round: game.combat.round,\n turn: game.combat.turn,\n hasLeft: false,\n };\n\n const castTurn = targetItemTracker.startRound === game.combat.round && targetItemTracker.startTurn === game.combat.turn;\n const isLaterTurn = game.combat.round > targetTokenTracker.round || game.combat.turn > targetTokenTracker.turn;\n\n // if:\n // not cast turn, and not part of the original target\n // AND one of the following\n // not original template and have not yet had this effect applied this combat OR\n // has been targeted this combat, left and re-entered effect, and is a later turn\n if (castTurn && originalTarget) {\n console.debug(`Token ${target.name} is part of the original target for ${item.name}`);\n } else if (!targetedThisCombat || (targetedThisCombat && targetTokenTracker.hasLeft && isLaterTurn)){\n console.debug(`Token ${target.name} is targeted for immediate damage with ${item.name}, using the following factors`, { originalTarget, castTurn, targetedThisCombat, targetTokenTracker, isLaterTurn });\n targetTokenTracker.hasLeft = false;\n await rollItemDamage(target, lastArg.efData.origin, targetItemTracker.spellLevel);\n }\n await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);\n} else if (args[0] == \"off\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const target = canvas.tokens.get(lastArg.tokenId);\n const targetTokenTracker = DAE.getFlag(target, `${safeName}Tracker`);\n\n if (targetTokenTracker) {\n targetTokenTracker.hasLeft = true;\n targetTokenTracker.turn = game.combat.turn;\n targetTokenTracker.round = game.combat.round;\n await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);\n }\n}","folder":"Xnvpa6bGFYi4yoqK","flags":{"advanced-macros":{"runAsGM":false}},"author":"xOFiqDVDAkPwiqtI","sort":0,"ownership":{"default":0,"xOFiqDVDAkPwiqtI":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.291","createdTime":1672646161120,"modifiedTime":1672646161120,"lastModifiedBy":"xOFiqDVDAkPwiqtI"},"_id":"IfxT63Ay2HWaSmWC"}
|
||
{"name":"Active Aura Damage and Condition On Entry (Generic)","type":"script","img":"icons/svg/dice-target.svg","scope":"global","command":"if(!game.modules.get(\"ActiveAuras\")?.active) {\n ui.notifications.error(\"ActiveAuras is not enabled\");\n return;\n}\n\nconst lastArg = args[args.length - 1];\n\nasync function wait(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); }\n\nfunction getHighestAbility(actor, abilities) {\n if (typeof abilities === \"string\") {\n return abilities;\n } else if (Array.isArray(abilities)) {\n return abilities.reduce((prv, current) => {\n if (actor.system.abilities[current].value > actor.system.abilities[prv].value) return current;\n else return prv;\n }, abilities[0]);\n }\n}\n\nfunction getCantripDice(actor) {\n const level = actor.type === \"character\" ? actor.system.details.level : actor.system.details.cr;\n return 1 + Math.floor((level + 1) / 6);\n}\n\n\nasync function attemptRemoval(targetToken, condition, item) {\n if (game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n new Dialog({\n title: `Use action to attempt to remove ${condition}?`,\n buttons: {\n one: {\n label: \"Yes\",\n callback: async () => {\n const caster = item.parent;\n const saveDc = caster.system.attributes.spelldc;\n const removalCheck = item.system.flags.ddbimporter.effect.removalCheck;\n const removalSave = item.system.flags.ddbimporter.effect.removalSave;\n const ability = removalCheck ? getHighestAbility(targetToken.actor.data, removalCheck) : getHighestAbility(targetToken.actor.data, removalSave);\n const type = removalCheck ? \"check\" : \"save\";\n const flavor = `${condition} (via ${item.name}) : ${CONFIG.DND5E.abilities[ability]} ${type} vs DC${saveDc}`;\n const rollResult = removalCheck\n ? (await targetToken.actor.rollAbilityTest(ability, { flavor })).total\n : (await targetToken.actor.rollAbilitySave(ability, { flavor })).total;\n\n if (rollResult >= saveDc) {\n game.dfreds.effectInterface.removeEffect({ effectName: condition, uuid: targetToken.document.uuid });\n } else {\n if (rollResult < saveDc) ChatMessage.create({ content: `${targetToken.name} fails the ${type} for ${item.name}, still has the ${condition} condition.` });\n }\n },\n },\n two: {\n label: \"No\",\n callback: () => {},\n },\n },\n }).render(true);\n }\n}\n\nasync function applyCondition(condition, targetToken, item, itemLevel) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n const caster = item.parent;\n const workflowItemData = duplicate(item.data);\n workflowItemData.system.target = { value: 1, units: \"\", type: \"creature\" };\n workflowItemData.system.save.ability = item.flags.ddbimporter.effect.save;\n workflowItemData.system.components.concentration = false;\n workflowItemData.system.level = itemLevel;\n workflowItemData.system.duration = { value: null, units: \"inst\" };\n workflowItemData.system.target = { value: null, width: null, units: \"\", type: \"creature\" };\n workflowItemData.system.preparation.mode = \"atwill\";\n setProperty(workflowItemData, \"flags.itemacro\", {});\n setProperty(workflowItemData, \"flags.midi-qol\", {});\n setProperty(workflowItemData, \"flags.dae\", {});\n setProperty(workflowItemData, \"effects\", []);\n delete workflowItemData._id;\n workflowItemData.name = `${workflowItemData.name}: ${item.name} Condition save`;\n // console.warn(\"workflowItemData\", workflowItemData);\n\n const saveTargets = [...game.user?.targets].map((t )=> t.id);\n game.user.updateTokenTargets([targetToken.id]);\n const saveItem = new CONFIG.Item.documentClass(workflowItemData, { parent: caster });\n const options = { showFullCard: false, createWorkflow: true, configureDialog: true };\n const result = await MidiQOL.completeItemRoll(saveItem, options);\n\n game.user.updateTokenTargets(saveTargets);\n const failedSaves = [...result.failedSaves];\n if (failedSaves.length > 0) {\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: failedSaves[0].document.uuid });\n }\n\n return result;\n }\n}\n\nasync function attachSequencerFileToTemplate(templateUuid, sequencerFile, originUuid) {\n if (game.modules.get(\"sequencer\")?.active) {\n if (Sequencer.Database.entryExists(sequencerFile)) {\n console.debug(`Trying to apply sequencer effect (${sequencerFile}) to ${templateUuid} from ${originUuid}`, sequencerFile);\n const template = await fromUuid(templateUuid);\n new Sequence()\n .effect()\n .file(Sequencer.Database.entryExists(sequencerFile))\n .size({\n width: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n height: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n })\n .persist(true)\n .origin(originUuid)\n .belowTokens()\n .opacity(0.5)\n .attachTo(template, { followRotation: true })\n .stretchTo(template, { attachTo: true})\n .play();\n }\n }\n}\n\n\nasync function rollItemDamage(targetToken, itemUuid, itemLevel) {\n const item = await fromUuid(itemUuid);\n const caster = item.parent;\n const isCantrip = item.flags.ddbimporter.effect.isCantrip;\n const damageDice = item.flags.ddbimporter.effect.dice;\n const damageType = item.flags.ddbimporter.effect.damageType;\n const saveAbility = item.flags.ddbimporter.effect.save;\n const casterToken = canvas.tokens.placeables.find((t) => t.actor?.uuid === caster.uuid);\n const scalingDiceArray = item.system.scaling.formula.split(\"d\");\n const scalingDiceNumber = itemLevel - item.system.level;\n const upscaledDamage = isCantrip\n ? `${getCantripDice(caster.data)}d${scalingDiceArray[1]}[${damageType}]`\n : scalingDiceNumber > 0 ? `${scalingDiceNumber}d${scalingDiceArray[1]}[${damageType}] + ${damageDice}` : damageDice;\n const damageRoll = await new Roll(upscaledDamage).evaluate({ async: true });\n if (game.dice3d) game.dice3d.showForRoll(damageRoll);\n const workflowItemData = duplicate(item.data);\n workflowItemData.system.target = { value: 1, units: \"\", type: \"creature\" };\n workflowItemData.system.save.ability = saveAbility;\n workflowItemData.system.components.concentration = false;\n workflowItemData.system.level = itemLevel;\n workflowItemData.system.duration = { value: null, units: \"inst\" };\n workflowItemData.system.target = { value: null, width: null, units: \"\", type: \"creature\" };\n\n setProperty(workflowItemData, \"flags.itemacro\", {});\n setProperty(workflowItemData, \"flags.midi-qol\", {});\n setProperty(workflowItemData, \"flags.dae\", {});\n setProperty(workflowItemData, \"effects\", []);\n delete workflowItemData._id;\n workflowItemData.name = `${workflowItemData.name}: Turn Entry Damage`;\n // console.warn(\"workflowItemData\", workflowItemData);\n\n await new MidiQOL.DamageOnlyWorkflow(\n caster,\n casterToken,\n damageRoll.total,\n damageType,\n [targetToken],\n damageRoll,\n {\n flavor: `(${CONFIG.DND5E.damageTypes[damageType]})`,\n itemCardId: \"new\",\n itemData: workflowItemData,\n isCritical: false,\n }\n );\n}\n\nif (args[0].tag === \"OnUse\" && args[0].macroPass === \"preActiveEffects\") {\n const safeName = lastArg.itemData.name.replace(/\\s|'|\\.|’/g, \"_\");\n const dataTracker = {\n randomId: randomID(),\n targetUuids: lastArg.targetUuids,\n startRound: game.combat.round,\n startTurn: game.combat.turn,\n spellLevel: lastArg.spellLevel,\n };\n\n const item = await fromUuid(lastArg.itemUuid);\n // await item.update(dataTracker);\n await DAE.unsetFlag(item, `${safeName}Tracker`);\n await DAE.setFlag(item, `${safeName}Tracker`, dataTracker);\n\n const ddbEffectFlags = lastArg.item.flags.ddbimporter?.effect;\n if (ddbEffectFlags) {\n const sequencerFile = ddbEffectFlags.sequencerFile;\n if (sequencerFile) {\n await attachSequencerFileToTemplate(lastArg.templateUuid, sequencerFile, lastArg.itemUuid)\n }\n if (ddbEffectFlags.isCantrip) {\n const cantripDice = getCantripDice(lastArg.actor);\n args[0].spellLevel = cantripDice;\n ddbEffectFlags.cantripDice = cantripDice;\n let newEffects = args[0].item.effects.map((effect) => {\n effect.changes = effect.changes.map((change) => {\n change.value = change.value.replace(\"@cantripDice\", cantripDice)\n return change;\n });\n return effect;\n });\n args[0].item.effects = duplicate(newEffects);\n args[0].itemData.effects = duplicate(newEffects);\n }\n const template = await fromUuid(lastArg.templateUuid);\n await template.update({\"flags.effect\": ddbEffectFlags});\n\n if (ddbEffectFlags.applyImmediate) {\n console.debug(\"Applying immediate effect\");\n await wait(500);\n const condition = ddbEffectFlags.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n }\n\n console.debug(\"ItemMacro: Pre-apply finised, applying effect to template\")\n\n return await AAhelpers.applyTemplate(args);\n\n} else if (args[0].tag === \"OnUse\" && args[0].macroPass === \"postActiveEffects\") {\n if (lastArg.item.flags.ddbimporter?.effect?.applyImmediate) {\n const condition = lastArg.item.flags.ddbimporter.effect.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n} else if (args[0] == \"on\" || args[0] == \"each\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const item = await fromUuid(lastArg.efData.origin);\n const ddbEffectFlags = item.flags.ddbimporter.effect;\n // sometimes the round info has not updated, so we pause a bit\n if (args[0] == \"each\") await wait(500);\n const targetItemTracker = DAE.getFlag(item.parent, `${safeName}Tracker`);\n const originalTarget = targetItemTracker.targetUuids.includes(lastArg.tokenUuid);\n const target = canvas.tokens.get(lastArg.tokenId);\n const targetTokenTrackerFlag = DAE.getFlag(target, `${safeName}Tracker`);\n const targetedThisCombat = targetTokenTrackerFlag && targetItemTracker.randomId === targetTokenTrackerFlag.randomId;\n const targetTokenTracker = targetedThisCombat\n ? targetTokenTrackerFlag\n : {\n randomId: targetItemTracker.randomId,\n round: game.combat.round,\n turn: game.combat.turn,\n hasLeft: false,\n condition: ddbEffectFlags.condition,\n };\n\n const castTurn = targetItemTracker.startRound === game.combat.round && targetItemTracker.startTurn === game.combat.turn;\n const isLaterTurn = game.combat.round > targetTokenTracker.round || game.combat.turn > targetTokenTracker.turn;\n const everyEntry = hasProperty(item.data, \"flags.ddbimporter.effect.everyEntry\")\n ? item.flags.ddbimporter.effect.everyEntry\n : false;\n\n // if:\n // not cast turn, and not part of the original target\n // AND one of the following\n // not original template and have not yet had this effect applied this combat OR\n // has been targeted this combat, left and re-entered effect, and is a later turn\n\n const autoDamageIfCondition = hasProperty(ddbEffectFlags, \"autoDamageIfCondition\") ? ddbEffectFlags.autoDamageIfCondition : false;\n const hasConditionStart = game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, target.actor.uuid);\n const applyAutoConditionDamage = autoDamageIfCondition && hasConditionStart;\n\n if (ddbEffectFlags.conditionEffect && !hasConditionStart) {\n if (castTurn && originalTarget) {\n console.debug(`Token ${target.name} is part of the original target for ${item.name}`);\n } else if (everyEntry || !targetedThisCombat || (targetedThisCombat && isLaterTurn)) {\n console.debug(`Token ${target.name} is targeted for immediate save vs condition with ${item.name}, using the following factors`, { originalTarget, castTurn, targetedThisCombat, targetTokenTracker, isLaterTurn });\n targetTokenTracker.hasLeft = false;\n await applyCondition(targetTokenTracker.condition, target, item, targetItemTracker.spellLevel);\n } else {\n console.debug(`Token ${target.name} has not evaluated for condition application`);\n }\n }\n if (ddbEffectFlags.damageEffect) {\n if (castTurn && originalTarget) {\n console.debug(`Token ${target.name} is part of the original target for ${item.name}`);\n } else if ((!targetedThisCombat && !autoDamageIfCondition) || //if auto damage applied by conditional save\n (targetedThisCombat && ((targetTokenTracker.hasLeft && isLaterTurn) || (applyAutoConditionDamage && isLaterTurn)))\n ) {\n console.debug(`Token ${target.name} is targeted for immediate damage with ${item.name}, using the following factors`, { originalTarget, castTurn, targetedThisCombat, targetTokenTracker, isLaterTurn });\n targetTokenTracker.hasLeft = false;\n await rollItemDamage(target, lastArg.efData.origin, targetItemTracker.spellLevel);\n } else {\n console.debug(`Token ${target.name} has not evaluated for damage application`);\n }\n }\n\n targetTokenTracker.turn = game.combat.turn;\n targetTokenTracker.round = game.combat.round;\n await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);\n const allowVsRemoveCondition = item.flags.ddbimporter.effect.allowVsRemoveCondition;\n const hasConditionAppliedEnd = game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, target.document.uuid);\n const currentTokenCombatTurn = game.combat.current.tokenId === lastArg.tokenId;\n if (currentTokenCombatTurn && allowVsRemoveCondition && hasConditionAppliedEnd) {\n console.warn(`Asking ${target.name} wants to remove ${targetTokenTracker.condition}`);\n await attemptRemoval(target, targetTokenTracker.condition, item);\n }\n} else if (args[0] == \"off\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const targetToken = await fromUuid(lastArg.tokenUuid);\n const targetTokenTracker = await DAE.getFlag(targetToken, `${safeName}Tracker`);\n const removeOnOff = hasProperty(lastArg, \"efData.flags.ddbimporter.effect.removeOnOff\")\n ? lastArg.efData.flags.ddbimporter.effect.removeOnOff\n : true;\n\n if (targetTokenTracker?.condition && removeOnOff && game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, lastArg.tokenUuid)) {\n console.debug(`Removing ${targetTokenTracker.condition} from ${targetToken.name}`);\n game.dfreds.effectInterface.removeEffect({ effectName: targetTokenTracker.condition, uuid: lastArg.tokenUuid });\n }\n\n if (targetTokenTracker) {\n targetTokenTracker.hasLeft = true;\n await DAE.setFlag(targetToken, `${safeName}Tracker`, targetTokenTracker);\n }\n}","folder":"Xnvpa6bGFYi4yoqK","flags":{"advanced-macros":{"runAsGM":false}},"author":"xOFiqDVDAkPwiqtI","sort":0,"ownership":{"default":0,"xOFiqDVDAkPwiqtI":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.291","createdTime":1672646160477,"modifiedTime":1672646160477,"lastModifiedBy":"xOFiqDVDAkPwiqtI"},"_id":"WGHcYsxRUkvg0dR1"}
|
||
{"name":"Darkness (DDB - GM)","type":"script","img":"icons/magic/unholy/orb-glowing-yellow-purple.webp","scope":"global","command":"// This Macro is called by the Darkness spell so players can place walls and lights.\n\nconst darknessParams = args[args.length - 1];\n\nfunction circleWall(cx, cy, radius) {\n let walls = [];\n const step = 30;\n for (let i = step; i <= 360; i += step) {\n let theta0 = Math.toRadians(i - step);\n let theta1 = Math.toRadians(i);\n\n let lastX = Math.floor(radius * Math.cos(theta0) + cx);\n let lastY = Math.floor(radius * Math.sin(theta0) + cy);\n let newX = Math.floor(radius * Math.cos(theta1) + cx);\n let newY = Math.floor(radius * Math.sin(theta1) + cy);\n\n walls.push({\n c: [lastX, lastY, newX, newY],\n move: CONST.WALL_MOVEMENT_TYPES.NONE,\n light: CONST.WALL_SENSE_TYPES.NORMAL,\n sight: CONST.WALL_SENSE_TYPES.NORMAL,\n sound: CONST.WALL_SENSE_TYPES.NONE,\n dir: CONST.WALL_DIRECTIONS.BOTH,\n door: CONST.WALL_DOOR_TYPES.NONE,\n ds: CONST.WALL_DOOR_STATES.CLOSED,\n flags: {\n spellEffects: {\n Darkness: {\n ActorId: darknessParams.targetActorId,\n },\n },\n },\n });\n }\n\n canvas.scene.createEmbeddedDocuments(\"Wall\", walls);\n}\n\nfunction darknessLight(cx, cy, radius) {\n const lightTemplate = {\n x: cx,\n y: cy,\n rotation: 0,\n walls: false,\n vision: false,\n config: {\n alpha: 0.5,\n angle: 0,\n bright: radius,\n coloration: 1,\n dim: 0,\n gradual: false,\n luminosity: -1,\n saturation: 0,\n contrast: 0,\n shadows: 0,\n animation: {\n speed: 5,\n intensity: 5,\n reverse: false,\n },\n darkness: {\n min: 0,\n max: 1,\n },\n color: null,\n },\n hidden: false,\n flags: {\n spellEffects: {\n Darkness: {\n ActorId: darknessParams.targetActorId,\n },\n },\n \"perfect-vision\": {\n sightLimit: 0,\n },\n },\n };\n canvas.scene.createEmbeddedDocuments(\"AmbientLight\", [lightTemplate]);\n}\n\nif (args[0] == \"on\") {\n if (!game.modules.get(\"perfect-vision\")?.active) circleWall(darknessParams.x, darknessParams.y, darknessParams.radius);\n darknessLight(darknessParams.x, darknessParams.y, darknessParams.distance);\n}\n\nif (args[0] == \"off\") {\n const darkWalls = canvas.walls.placeables.filter((w) => w.data.flags?.spellEffects?.Darkness?.ActorId === darknessParams.targetActorId);\n const wallArray = darkWalls.map((w) => w.id);\n const darkLights = canvas.lighting.placeables.filter((w) => w.data.flags?.spellEffects?.Darkness?.ActorId === darknessParams.targetActorId);\n const lightArray = darkLights.map((w) => w.id);\n await canvas.scene.deleteEmbeddedDocuments(\"Wall\", wallArray);\n await canvas.scene.deleteEmbeddedDocuments(\"AmbientLight\", lightArray);\n}","folder":"Xnvpa6bGFYi4yoqK","flags":{"advanced-macros":{"runAsGM":true}},"author":"xOFiqDVDAkPwiqtI","sort":0,"ownership":{"default":0,"xOFiqDVDAkPwiqtI":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.291","createdTime":1672646161288,"modifiedTime":1672646161288,"lastModifiedBy":"xOFiqDVDAkPwiqtI"},"_id":"aiZPfEnPWSiwDzD8"}
|
||
{"name":"Active Aura Condition On Entry (Generic)","type":"script","img":"icons/svg/dice-target.svg","scope":"global","command":"if(!game.modules.get(\"ActiveAuras\")?.active) {\n ui.notifications.error(\"ActiveAuras is not enabled\");\n return;\n}\n\nconst lastArg = args[args.length - 1];\n\nasync function wait(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); }\n\nasync function attemptRemoval(targetToken, condition, item) {\n if (game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n new Dialog({\n title: `Use action to attempt to remove ${condition}?`,\n buttons: {\n one: {\n label: \"Yes\",\n callback: async () => {\n const caster = item.parent;\n const saveDc = caster.system.attributes.spelldc;\n const removalCheck = item.flags.ddbimporter.effect.removalCheck;\n const removalSave = item.flags.ddbimporter.effect.removalSave;\n const ability = removalCheck ? removalCheck : removalSave;\n const type = removalCheck ? \"check\" : \"save\";\n const flavor = `${condition} (via ${item.name}) : ${CONFIG.DND5E.abilities[ability]} ${type} vs DC${saveDc}`;\n const rollResult = removalCheck\n ? (await targetToken.actor.rollAbilityTest(ability, { flavor })).total\n : (await targetToken.actor.rollAbilitySave(ability, { flavor })).total;\n\n if (rollResult >= saveDc) {\n game.dfreds.effectInterface.removeEffect({ effectName: condition, uuid: targetToken.document.uuid });\n } else {\n if (rollResult < saveDc) ChatMessage.create({ content: `${targetToken.name} fails the ${type} for ${item.name}, still has the ${condition} condition.` });\n }\n },\n },\n two: {\n label: \"No\",\n callback: () => {},\n },\n },\n }).render(true);\n }\n}\n\nasync function applyCondition(condition, targetToken, item, itemLevel) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, targetToken.document.uuid)) {\n const caster = item.parent;\n const workflowItemData = duplicate(item.data);\n workflowItemData.system.target = { value: 1, units: \"\", type: \"creature\" };\n workflowItemData.system.save.ability = item.flags.ddbimporter.effect.save;\n workflowItemData.system.components.concentration = false;\n workflowItemData.system.level = itemLevel;\n workflowItemData.system.duration = { value: null, units: \"inst\" };\n workflowItemData.system.target = { value: null, width: null, units: \"\", type: \"creature\" };\n workflowItemData.system.preparation.mode = \"atwill\";\n setProperty(workflowItemData, \"flags.itemacro\", {});\n setProperty(workflowItemData, \"flags.midi-qol\", {});\n setProperty(workflowItemData, \"flags.dae\", {});\n setProperty(workflowItemData, \"effects\", []);\n delete workflowItemData._id;\n workflowItemData.name = `${workflowItemData.name}: ${item.name} Condition save`;\n // console.warn(\"workflowItemData\", workflowItemData);\n\n const saveTargets = [...game.user?.targets].map((t )=> t.id);\n game.user.updateTokenTargets([targetToken.id]);\n const saveItem = new CONFIG.Item.documentClass(workflowItemData, { parent: caster });\n const options = { showFullCard: false, createWorkflow: true, configureDialog: true };\n const result = await MidiQOL.completeItemRoll(saveItem, options);\n\n game.user.updateTokenTargets(saveTargets);\n const failedSaves = [...result.failedSaves];\n if (failedSaves.length > 0) {\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: failedSaves[0].document.uuid });\n }\n\n return result;\n }\n}\n\nasync function attachSequencerFileToTemplate(templateUuid, sequencerFile, originUuid) {\n if (game.modules.get(\"sequencer\")?.active) {\n if (Sequencer.Database.entryExists(sequencerFile)) {\n console.debug(`Trying to apply sequencer effect (${sequencerFile}) to ${templateUuid} from ${originUuid}`, sequencerFile);\n const template = await fromUuid(templateUuid);\n new Sequence()\n .effect()\n .file(Sequencer.Database.entryExists(sequencerFile))\n .size({\n width: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n height: canvas.grid.size * (template.data.width / canvas.dimensions.distance),\n })\n .persist(true)\n .origin(originUuid)\n .belowTokens()\n .opacity(0.5)\n .attachTo(template, { followRotation: true })\n .stretchTo(template, { attachTo: true})\n .play();\n }\n }\n}\n\nif (args[0].tag === \"OnUse\" && args[0].macroPass === \"preActiveEffects\") {\n const safeName = lastArg.itemData.name.replace(/\\s|'|\\.|’/g, \"_\");\n const dataTracker = {\n randomId: randomID(),\n targetUuids: lastArg.targetUuids,\n startRound: game.combat.round,\n startTurn: game.combat.turn,\n spellLevel: lastArg.spellLevel,\n };\n\n const item = await fromUuid(lastArg.itemUuid);\n // await item.update(dataTracker);\n await DAE.unsetFlag(item, `${safeName}Tracker`);\n await DAE.setFlag(item, `${safeName}Tracker`, dataTracker);\n\n const sequencerFile = lastArg.item.flags.ddbimporter?.effect?.sequencerFile;\n if (sequencerFile) {\n attachSequencerFileToTemplate(lastArg.templateUuid, sequencerFile, lastArg.itemUuid)\n }\n\n if (lastArg.item.flags.ddbimporter?.effect?.applyImmediate) {\n await wait(500);\n const condition = lastArg.item.flags.ddbimporter.effect.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n\n return await AAhelpers.applyTemplate(args);\n\n} else if (args[0].tag === \"OnUse\" && args[0].macroPass === \"postActiveEffects\") {\n if (lastArg.item.flags.ddbimporter?.effect?.applyImmediate) {\n const condition = lastArg.item.flags.ddbimporter.effect.condition;\n for (const token of lastArg.failedSaves) {\n if (!game.dfreds.effectInterface.hasEffectApplied(condition, token.actor.uuid)) {\n console.debug(`Applying ${condition} to ${token.name}`);\n await game.dfreds.effectInterface.addEffect({ effectName: condition, uuid: token.actor.uuid });\n }\n };\n }\n} else if (args[0] == \"on\" || args[0] == \"each\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const item = await fromUuid(lastArg.efData.origin);\n // sometimes the round info has not updated, so we pause a bit\n if (args[0] == \"each\") await wait(500);\n const targetItemTracker = DAE.getFlag(item.parent, `${safeName}Tracker`);\n const originalTarget = targetItemTracker.targetUuids.includes(lastArg.tokenUuid);\n const target = canvas.tokens.get(lastArg.tokenId);\n const targetTokenTrackerFlag = DAE.getFlag(target, `${safeName}Tracker`);\n const targetedThisCombat = targetTokenTrackerFlag && targetItemTracker.randomId === targetTokenTrackerFlag.randomId;\n const targetTokenTracker = targetedThisCombat\n ? targetTokenTrackerFlag\n : {\n randomId: targetItemTracker.randomId,\n round: game.combat.round,\n turn: game.combat.turn,\n hasLeft: false,\n condition: item.flags.ddbimporter.effect.condition,\n };\n\n const castTurn = targetItemTracker.startRound === game.combat.round && targetItemTracker.startTurn === game.combat.turn;\n const isLaterTurn = game.combat.round > targetTokenTracker.round || game.combat.turn > targetTokenTracker.turn;\n const everyEntry = hasProperty(item.data, \"flags.ddbimporter.effect.everyEntry\")\n ? item.flags.ddbimporter.effect.everyEntry\n : false;\n\n // if:\n // not cast turn, and not part of the original target\n // AND one of the following\n // not original template and have not yet had this effect applied this combat OR\n // has been targeted this combat, left and re-entered effect, and is a later turn\n\n if (castTurn && originalTarget) {\n console.debug(`Token ${target.name} is part of the original target for ${item.name}`);\n } else if (everyEntry || !targetedThisCombat || (targetedThisCombat && isLaterTurn)) {\n console.debug(`Token ${target.name} is targeted for immediate save vs condition with ${item.name}, using the following factors`, { originalTarget, castTurn, targetedThisCombat, targetTokenTracker, isLaterTurn });\n targetTokenTracker.hasLeft = false;\n await applyCondition(targetTokenTracker.condition, target, item, targetItemTracker.spellLevel);\n }\n await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);\n const allowVsRemoveCondition = item.flags.ddbimporter.effect.allowVsRemoveCondition;\n const effectApplied = game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, target.document.uuid);\n const currentTokenCombatTurn = game.combat.current.tokenId === lastArg.tokenId;\n if (currentTokenCombatTurn && allowVsRemoveCondition && effectApplied) {\n console.warn(`Removing ${targetTokenTracker.condition}`);\n await attemptRemoval(target, targetTokenTracker.condition, item);\n }\n} else if (args[0] == \"off\") {\n const safeName = lastArg.efData.label.replace(/\\s|'|\\.|’/g, \"_\");\n const targetToken = await fromUuid(lastArg.tokenUuid);\n const targetTokenTracker = await DAE.getFlag(targetToken, `${safeName}Tracker`);\n const removeOnOff = hasProperty(lastArg, \"efData.flags.ddbimporter.effect.removeOnOff\")\n ? lastArg.efData.flags.ddbimporter.effect.removeOnOff\n : true;\n\n if (targetTokenTracker?.condition && removeOnOff && game.dfreds.effectInterface.hasEffectApplied(targetTokenTracker.condition, lastArg.tokenUuid)) {\n console.debug(`Removing ${targetTokenTracker.condition} from ${targetToken.name}`);\n game.dfreds.effectInterface.removeEffect({ effectName: targetTokenTracker.condition, uuid: lastArg.tokenUuid });\n }\n\n if (targetTokenTracker) {\n targetTokenTracker.hasLeft = true;\n targetTokenTracker.turn = game.combat.turn;\n targetTokenTracker.round = game.combat.round;\n await DAE.setFlag(targetToken, `${safeName}Tracker`, targetTokenTracker);\n }\n}","folder":"Xnvpa6bGFYi4yoqK","flags":{"advanced-macros":{"runAsGM":false}},"author":"xOFiqDVDAkPwiqtI","sort":0,"ownership":{"default":0,"xOFiqDVDAkPwiqtI":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.291","createdTime":1672646160590,"modifiedTime":1672646160590,"lastModifiedBy":"xOFiqDVDAkPwiqtI"},"_id":"joyyEVZhl9n6atWK"}
|