Foundry VTT/P2FE: Difference between revisions

From Omnia
Jump to navigation Jump to search
(Created page with "== Macros == === Raise Shield === <pre> game.pf2e.actions.raiseAShield({ actors: [token?.actor ?? actor ?? game.user.character].filter((actor) => actor) }) </pre> === Scouting === <pre> const actors = game.user.getActiveTokens().flatMap((t) => t.actor ?? []); if (actors.length === 0) { return ui.notifications.error("PF2E.ErrorMessage.NoTokenSelected", { localize: true }); } const ITEM_UUID = "Compendium.pf2e.other-effects.Item.EMqGwUi3VMhCjTlF"; // Effect: Scout...")
 
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Macros ==
== Macros ==
=== Basic Action Macro ===
<pre>
await game.PF2eWorkbench.basicActionMacros();
</pre>
=== Camping Sheet ===
<pre>
game.pf2eKingmakerTools.macros.openCampingSheet()
</pre>
=== Exploration ===
<pre>
const tokens = canvas.tokens.controlled.filter((t) =>
  ['character'].includes(t.actor.type),
)
if (tokens.length === 0) {
  ui.notifications.error(`You must select at least one pc token`)
} else {
  tokens.forEach((token) => {
    let actor = token.actor
    let tokenID = token.id
    explorationActivity(actor, tokenID)
  })
}
function explorationActivity(actor, tokenID) {
  let token = canvas.tokens.get(tokenID)
  let content = ''
  let selectedActivity
  let activities = {
    'Avoid Notice':
      '@Compendium[pf2e.actionspf2e.IE2nThCmoyhQA0Jn]{Avoid Notice}',
    'Cover Tracks':
      '@Compendium[pf2e.actionspf2e.SB7cMECVtE06kByk]{Cover Tracks}',
    Defend: '@Compendium[pf2e.actionspf2e.cYtYKa1gDEl7y2N0]{Defend}',
    'Detect Magic':
      '@Compendium[pf2e.actionspf2e.Yb0C1uLzeHrVLl7a]{Detect Magic}',
    'Follow the Expert':
      '@Compendium[pf2e.actionspf2e.tfa4Sh7wcxCEqL29]{Follow the Expert}',
    Hustle: '@Compendium[pf2e.actionspf2e.JuqmIAnkL9hVGai8]{Hustle}',
    Investigate: '@Compendium[pf2e.actionspf2e.EwgTZBWsc8qKaViP]{Investigate}',
    'Repeat a Spell':
      '@Compendium[pf2e.actionspf2e.OQaFzDtVEOMWizJJ]{Repeat a Spell}',
    Scout: '@Compendium[pf2e.actionspf2e.kV3XM0YJeS2KCSOb]{Scout}',
    Search: '@Compendium[pf2e.actionspf2e.TiNDYUGlMmxzxBYU]{Search}',
    Track: '@Compendium[pf2e.actionspf2e.EA5vuSgJfiHH7plD]{Track}',
  }
  let additionalActions = {
    'Borrow an Arcane Spell':
      '@Compendium[pf2e.actionspf2e.OizxuPb44g3eHPFh]{Borrow an Arcane Spell}',
    Coerce: '@Compendium[pf2e.actionspf2e.tHCqgwjtQtzNqVvd]{Coerce}',
    'Cover Tracks':
      '@Compendium[pf2e.actionspf2e.SB7cMECVtE06kByk]{Cover Tracks}',
    'Decipher Writing':
      '@Compendium[pf2e.actionspf2e.d9gbpiQjChYDYA2L]{Decypher Writing}',
    'Gather Information':
      '@Compendium[pf2e.actionspf2e.plBGdZhqq5JBl1D8]{Gather Information}',
    'Identify Alchemy':
      '@Compendium[pf2e.actionspf2e.Q4kdWVOf2ztIBFg1]{Identify Alchemy}',
    'Identify Magic':
      '@Compendium[pf2e.actionspf2e.eReSHVEPCsdkSL4G]{Identify Magic}',
    Impersonate: '@Compendium[pf2e.actionspf2e.AJstokjdG6iDjVjE]{Impersonate}',
    'Learn a Spell':
      '@Compendium[pf2e.actionspf2e.Q5iIYCFdqJFM31GW]{Learn a Spell}',
    'Make an Impression':
      '@Compendium[pf2e.actionspf2e.OX4fy22hQgUHDr0q]{Make an Impression}',
    'Sense Direction':
      '@Compendium[pf2e.actionspf2e.fJImDBQfqfjKJOhk]{Sense Direction}',
    Squeeze: '@Compendium[pf2e.actionspf2e.kMcV8e5EZUxa6evt]{Squeeze}',
    'Treat Wounds':
      '@Compendium[pf2e.actionspf2e.1kGNdIIhuglAjIp9]{Treat Wounds}',
  }
  //contentUpdate();
  const dialogStyle = `
  <style>
    .my-class {
      margin-bottom: 12px;
    }
  </style>`
  content = dialogStyle
  content += `<div id="pf2e-explorationActivity-scripts-content"><label for="activity">Choose an activity: </label>
    <select class ="my-class"  name="activity" id="activity">`
  content += `<optgroup label="common">`
  for (let i = 0; i < Object.keys(activities).length; i++) {
    content += `<option value="${activities[Object.keys(activities)[i]]}">${
      Object.keys(activities)[i]
    }</option>`
  }
  content += `</optgroup>`
  content += `<optgroup label="additional">`
  for (let i = 0; i < Object.keys(additionalActions).length; i++) {
    content += `<option value="${
      additionalActions[Object.keys(additionalActions)[i]]
    }">${Object.keys(additionalActions)[i]}</option>`
  }
  content += `</optgroup>`
  content += `</select></div>`
  let d = new Dialog({
    title: 'Exploration Activity',
    content,
    buttons: {
      select: {
        icon: '',
        label: 'Select',
        callback: (html) => {
          selectedActivity =
            '<h3>I will <b>' + html.find('#activity')[0].value + '</b></h3>'
          generateChat(actor, selectedActivity)
          applyEffect(actor, html.find('#activity')[0].value)
        },
      },
      cancel: {
        icon: '',
        label: 'Cancel',
        callback: () => {
          selectedActivity = '<h3>I will do nothing in particular.</h3>'
          generateChat(actor, selectedActivity)
        },
      },
    },
  })
  d.options.width = 250
  d.position.width = 250
  d.render(true)
  // used to create the chat messages
  async function generateChat(actor, output) {
    let chatData = {
      user: game.user._id,
      speaker: {
        alias: actor.name,
      },
      content: output,
    }
    await ChatMessage.create(chatData, {})
  }
  //used to apply effect
  async function applyEffect(actor, selectedEffect) {
    const re = /\{(.*)\}/i
    let effectName = selectedEffect.match(re)[1]
    const explorationEffects = {
      'Avoid Notice':
        'Compendium.pf2e-exploration-effects.exploration-effects.N8vpuGy4TzU10y8E',
      'Cover Tracks':
        'Compendium.pf2e-exploration-effects.exploration-effects.F6vJYLZTWDpnrnCZ',
      Defend:
        'Compendium.pf2e-exploration-effects.exploration-effects.GYOyFj4ziZX060rZ',
      'Detect Magic':
        'Compendium.pf2e-exploration-effects.exploration-effects.OjRHL0B4WAUUQc13',
      'Follow the Expert':
        'ompendium.pf2e-exploration-effects.exploration-effects.V347nnVBGDrVWh7k',
      Hustle:
        'Compendium.pf2e-exploration-effects.exploration-effects.vNUrKvoOSvEnqzhM',
      Investigate:
        'Compendium.pf2e-exploration-effects.exploration-effects.tDsgl8YmhZbx2May',
      'Repeat a Spell':
        'Compendium.pf2e-exploration-effects.exploration-effects.kh1QdKkvbNZ0qBsQ',
      Scout:
        'Compendium.pf2e-exploration-effects.exploration-effects.mGFBHM1lvHNZ9BsH',
      Search:
        'Compendium.pf2e-exploration-effects.exploration-effects.XiVLHjg5lQVMX8Fj',
      Track:
        'Compendium.pf2e-exploration-effects.exploration-effects.OcCXjJab7rSR3mDf',
    }
    let effect = explorationEffects[effectName]
    if (effect != undefined) {
      console.log('the effect is ' + effect)
      let item = (await fromUuid(effect)).toObject()
      await token.actor.createEmbeddedDocuments('Item', [item])
    }
  }
}
</pre>


=== Raise Shield ===
=== Raise Shield ===
Line 5: Line 188:
<pre>
<pre>
game.pf2e.actions.raiseAShield({ actors: [token?.actor ?? actor ?? game.user.character].filter((actor) => actor) })
game.pf2e.actions.raiseAShield({ actors: [token?.actor ?? actor ?? game.user.character].filter((actor) => actor) })
</pre>
=== Recall Knowledge ===
<pre>
/** This compendium link macro will always call the most recent version from the compendium included with this module meaning you do not need to reimport newer versions. The source of the macros that get called is https://gitlab.com/symonsch/my-foundryvtt-macros/-/tree/main/PF2e */
/* Start of documentation from the original macro: */
/*
Based on the macro by bipedalshark and WesBelmont and Allalinor.
updated by darkim, Dalvyn, and julie.winchester
Recall Knowledge
This macro will roll several knowledge checks if no target is selected.
If one ore more targets are selected it will only roll the relevant knowledge skills and compare the result to the DC.
Handles lore skills (as far as possible)
Handles Cognitive Mutagen and other Bonus effects
Should pick up most single target trait based mods automatically now if predicates are set properly.
Limitations:
* Does not handle assurance.
* Does not handle things like bardic knowledge.
*/
/* End of original macro documentation. */
    async function _executeMacroByName(
        macroName,
        compendiumName = "xdy-pf2e-workbench.asymonous-benefactor-macros-internal"
    ) {
        const pack = game.packs.get(compendiumName);
        if (pack) {
            const macro_data = (await pack.getDocuments()).find((i) => i.name === macroName)?.toObject();
            if (macro_data) {
                const temp_macro = new Macro(macro_data);
                temp_macro.permission.default = CONST.DOCUMENT_PERMISSION_LEVELS.OWNER;
                temp_macro.execute();
            } else {
                ui.notifications.error("Macro " + macroName + " not found");
            }
        } else {
            ui.notifications.error("Compendium " + compendiumName + " not found");
        }
    }
    _executeMacroByName('XDY DO_NOT_IMPORT Recall_Knowledge');
    /* This compendium link macro is based on one originally posted by DrentalBot: https://discord.com/channels/880968862240239708/880975811279204402/910490804554973274; and modified by Mark Pearce https://discord.com/channels/880968862240239708/880969174661353484/972962446098702376 */
</pre>
=== Refocus ===
<pre>
await game.PF2eWorkbench.refocus();
</pre>
=== Reload ===
<pre>
game.pf2eRangedCombat.reload();
</pre>
</pre>


=== Scouting ===
=== Scouting ===
<pre>
game.pf2e.rollItemMacro("2FxTHADqPM7Y2MYA", event);
</pre>
or


<pre>
<pre>
Line 37: Line 283:
}
}
</pre>
</pre>
=== Strike Sword ===
Character Specific
<pre>
game.pf2e.rollActionMacro({ actorUUID: "Actor.hX3uMf6KxgObJ9ec",  type: "strike", itemId: "8PbktFIjqpi9Ht96", slug: "bastard-sword" })
</pre>
== keywords ==

Latest revision as of 02:44, 27 August 2024

Macros

Basic Action Macro

await game.PF2eWorkbench.basicActionMacros();

Camping Sheet

game.pf2eKingmakerTools.macros.openCampingSheet()

Exploration

const tokens = canvas.tokens.controlled.filter((t) =>
  ['character'].includes(t.actor.type),
)

if (tokens.length === 0) {
  ui.notifications.error(`You must select at least one pc token`)
} else {
  tokens.forEach((token) => {
    let actor = token.actor
    let tokenID = token.id
    explorationActivity(actor, tokenID)
  })
}

function explorationActivity(actor, tokenID) {
  let token = canvas.tokens.get(tokenID)
  let content = ''
  let selectedActivity
  let activities = {
    'Avoid Notice':
      '@Compendium[pf2e.actionspf2e.IE2nThCmoyhQA0Jn]{Avoid Notice}',
    'Cover Tracks':
      '@Compendium[pf2e.actionspf2e.SB7cMECVtE06kByk]{Cover Tracks}',
    Defend: '@Compendium[pf2e.actionspf2e.cYtYKa1gDEl7y2N0]{Defend}',
    'Detect Magic':
      '@Compendium[pf2e.actionspf2e.Yb0C1uLzeHrVLl7a]{Detect Magic}',
    'Follow the Expert':
      '@Compendium[pf2e.actionspf2e.tfa4Sh7wcxCEqL29]{Follow the Expert}',
    Hustle: '@Compendium[pf2e.actionspf2e.JuqmIAnkL9hVGai8]{Hustle}',
    Investigate: '@Compendium[pf2e.actionspf2e.EwgTZBWsc8qKaViP]{Investigate}',
    'Repeat a Spell':
      '@Compendium[pf2e.actionspf2e.OQaFzDtVEOMWizJJ]{Repeat a Spell}',
    Scout: '@Compendium[pf2e.actionspf2e.kV3XM0YJeS2KCSOb]{Scout}',
    Search: '@Compendium[pf2e.actionspf2e.TiNDYUGlMmxzxBYU]{Search}',
    Track: '@Compendium[pf2e.actionspf2e.EA5vuSgJfiHH7plD]{Track}',
  }

  let additionalActions = {
    'Borrow an Arcane Spell':
      '@Compendium[pf2e.actionspf2e.OizxuPb44g3eHPFh]{Borrow an Arcane Spell}',
    Coerce: '@Compendium[pf2e.actionspf2e.tHCqgwjtQtzNqVvd]{Coerce}',
    'Cover Tracks':
      '@Compendium[pf2e.actionspf2e.SB7cMECVtE06kByk]{Cover Tracks}',
    'Decipher Writing':
      '@Compendium[pf2e.actionspf2e.d9gbpiQjChYDYA2L]{Decypher Writing}',
    'Gather Information':
      '@Compendium[pf2e.actionspf2e.plBGdZhqq5JBl1D8]{Gather Information}',
    'Identify Alchemy':
      '@Compendium[pf2e.actionspf2e.Q4kdWVOf2ztIBFg1]{Identify Alchemy}',
    'Identify Magic':
      '@Compendium[pf2e.actionspf2e.eReSHVEPCsdkSL4G]{Identify Magic}',
    Impersonate: '@Compendium[pf2e.actionspf2e.AJstokjdG6iDjVjE]{Impersonate}',
    'Learn a Spell':
      '@Compendium[pf2e.actionspf2e.Q5iIYCFdqJFM31GW]{Learn a Spell}',
    'Make an Impression':
      '@Compendium[pf2e.actionspf2e.OX4fy22hQgUHDr0q]{Make an Impression}',
    'Sense Direction':
      '@Compendium[pf2e.actionspf2e.fJImDBQfqfjKJOhk]{Sense Direction}',
    Squeeze: '@Compendium[pf2e.actionspf2e.kMcV8e5EZUxa6evt]{Squeeze}',
    'Treat Wounds':
      '@Compendium[pf2e.actionspf2e.1kGNdIIhuglAjIp9]{Treat Wounds}',
  }

  //contentUpdate();
  const dialogStyle = `
  <style>
    .my-class {
      margin-bottom: 12px; 
    }
  </style>`
  content = dialogStyle
  content += `<div id="pf2e-explorationActivity-scripts-content"><label for="activity">Choose an activity: </label>
    <select class ="my-class"  name="activity" id="activity">`
  content += `<optgroup label="common">`
  for (let i = 0; i < Object.keys(activities).length; i++) {
    content += `<option value="${activities[Object.keys(activities)[i]]}">${
      Object.keys(activities)[i]
    }</option>`
  }
  content += `</optgroup>`
  content += `<optgroup label="additional">`
  for (let i = 0; i < Object.keys(additionalActions).length; i++) {
    content += `<option value="${
      additionalActions[Object.keys(additionalActions)[i]]
    }">${Object.keys(additionalActions)[i]}</option>`
  }
  content += `</optgroup>`
  content += `</select></div>`

  let d = new Dialog({
    title: 'Exploration Activity',
    content,
    buttons: {
      select: {
        icon: '',
        label: 'Select',
        callback: (html) => {
          selectedActivity =
            '<h3>I will <b>' + html.find('#activity')[0].value + '</b></h3>'
          generateChat(actor, selectedActivity)
          applyEffect(actor, html.find('#activity')[0].value)
        },
      },
      cancel: {
        icon: '',
        label: 'Cancel',
        callback: () => {
          selectedActivity = '<h3>I will do nothing in particular.</h3>'
          generateChat(actor, selectedActivity)
        },
      },
    },
  })
  d.options.width = 250
  d.position.width = 250
  d.render(true)

  // used to create the chat messages
  async function generateChat(actor, output) {
    let chatData = {
      user: game.user._id,
      speaker: {
        alias: actor.name,
      },
      content: output,
    }
    await ChatMessage.create(chatData, {})
  }

  //used to apply effect
  async function applyEffect(actor, selectedEffect) {
    const re = /\{(.*)\}/i
    let effectName = selectedEffect.match(re)[1]
    const explorationEffects = {
      'Avoid Notice':
        'Compendium.pf2e-exploration-effects.exploration-effects.N8vpuGy4TzU10y8E',
      'Cover Tracks':
        'Compendium.pf2e-exploration-effects.exploration-effects.F6vJYLZTWDpnrnCZ',
      Defend:
        'Compendium.pf2e-exploration-effects.exploration-effects.GYOyFj4ziZX060rZ',
      'Detect Magic':
        'Compendium.pf2e-exploration-effects.exploration-effects.OjRHL0B4WAUUQc13',
      'Follow the Expert':
        'ompendium.pf2e-exploration-effects.exploration-effects.V347nnVBGDrVWh7k',
      Hustle:
        'Compendium.pf2e-exploration-effects.exploration-effects.vNUrKvoOSvEnqzhM',
      Investigate:
        'Compendium.pf2e-exploration-effects.exploration-effects.tDsgl8YmhZbx2May',
      'Repeat a Spell':
        'Compendium.pf2e-exploration-effects.exploration-effects.kh1QdKkvbNZ0qBsQ',
      Scout:
        'Compendium.pf2e-exploration-effects.exploration-effects.mGFBHM1lvHNZ9BsH',
      Search:
        'Compendium.pf2e-exploration-effects.exploration-effects.XiVLHjg5lQVMX8Fj',
      Track:
        'Compendium.pf2e-exploration-effects.exploration-effects.OcCXjJab7rSR3mDf',
    }

    let effect = explorationEffects[effectName]
    if (effect != undefined) {
      console.log('the effect is ' + effect)
      let item = (await fromUuid(effect)).toObject()
      await token.actor.createEmbeddedDocuments('Item', [item])
    }
  }
}

Raise Shield

game.pf2e.actions.raiseAShield({ actors: [token?.actor ?? actor ?? game.user.character].filter((actor) => actor) })

Recall Knowledge

/** This compendium link macro will always call the most recent version from the compendium included with this module meaning you do not need to reimport newer versions. The source of the macros that get called is https://gitlab.com/symonsch/my-foundryvtt-macros/-/tree/main/PF2e */
/* Start of documentation from the original macro: */
/*
Based on the macro by bipedalshark and WesBelmont and Allalinor.
updated by darkim, Dalvyn, and julie.winchester

Recall Knowledge
This macro will roll several knowledge checks if no target is selected.
If one ore more targets are selected it will only roll the relevant knowledge skills and compare the result to the DC.
Handles lore skills (as far as possible)
Handles Cognitive Mutagen and other Bonus effects
Should pick up most single target trait based mods automatically now if predicates are set properly.

Limitations:
* Does not handle assurance.
* Does not handle things like bardic knowledge.
*/
/* End of original macro documentation. */

    async function _executeMacroByName(
        macroName,
        compendiumName = "xdy-pf2e-workbench.asymonous-benefactor-macros-internal"
    ) {
        const pack = game.packs.get(compendiumName);
        if (pack) {
            const macro_data = (await pack.getDocuments()).find((i) => i.name === macroName)?.toObject();
            if (macro_data) {
                const temp_macro = new Macro(macro_data);
                temp_macro.permission.default = CONST.DOCUMENT_PERMISSION_LEVELS.OWNER;
                temp_macro.execute();
            } else {
                ui.notifications.error("Macro " + macroName + " not found");
            }
        } else {
            ui.notifications.error("Compendium " + compendiumName + " not found");
        }
    }
    _executeMacroByName('XDY DO_NOT_IMPORT Recall_Knowledge');

    /* This compendium link macro is based on one originally posted by DrentalBot: https://discord.com/channels/880968862240239708/880975811279204402/910490804554973274; and modified by Mark Pearce https://discord.com/channels/880968862240239708/880969174661353484/972962446098702376 */

Refocus

await game.PF2eWorkbench.refocus();

Reload

game.pf2eRangedCombat.reload();

Scouting

game.pf2e.rollItemMacro("2FxTHADqPM7Y2MYA", event);

or

const actors = game.user.getActiveTokens().flatMap((t) => t.actor ?? []);
if (actors.length === 0) {
    return ui.notifications.error("PF2E.ErrorMessage.NoTokenSelected", { localize: true });
}

const ITEM_UUID = "Compendium.pf2e.other-effects.Item.EMqGwUi3VMhCjTlF"; // Effect: Scouting
const item = await fromUuid(ITEM_UUID);
if (item?.type === "condition") {
    for (const actor of actors) {
        actor.toggleCondition(item.slug);
    }
} else if (item?.type === "effect") {
    const source = item.toObject();
    source.flags = mergeObject(source.flags ?? {}, { core: { sourceId: ITEM_UUID } });

    for (const actor of actors) {
        const existing = actor.itemTypes.effect.find((e) => e.flags.core?.sourceId === ITEM_UUID);
        if (existing) {
            await existing.delete();
        } else {
            await actor.createEmbeddedDocuments("Item", [source]);
        }
    }
} else {
    ui.notifications.error(game.i18n.format("PF2E.ErrorMessage.ItemNotFoundByUUID", { uuid: ITEM_UUID }));
}

Strike Sword

Character Specific

game.pf2e.rollActionMacro({ actorUUID: "Actor.hX3uMf6KxgObJ9ec",  type: "strike", itemId: "8PbktFIjqpi9Ht96", slug: "bastard-sword" })

keywords