DFreds / dfreds-pocket-change

A FoundryVTT module that automatically adds money to NPC character sheets when dropped on the canvas.
MIT License
9 stars 7 forks source link

Add support for CUB triggers in macros #8

Closed DFreds closed 2 years ago

DFreds commented 3 years ago

Ask (via @dangerdaren): One concern is it might be best if instead of triggering on the selected token, I wonder if there is a way to make it apply to "whichever token triggered the event". Just in case I'm selecting someone else when an NPC dies. Maybe as simple as a new macro/line of code in existing macro to get triggered instead?

Use case: convert token to loot when token reaches 0 HP

Potential solution: Add support for passing a token in as an argument to all macros

DFreds commented 3 years ago

Regarding CUB specifically, this seems to be an open issue: https://github.com/death-save/combat-utility-belt/issues/453

Marking as blocked until CUB supports it.

SR5060 commented 3 years ago

I agree, this would be very handy. is there a way that the macro can check for a token that meets the criteria (NPC & HP at 0) so that it's not dependent on triggler for actor identification?

I had a macro that did this previously, but it appears broken with the v8 update.

DFreds commented 3 years ago

@SR5060 Do you mind posting the macro you're talking about? I can look into why it isn't working now, and it would help me understand what your use case was in detail.

SR5060 commented 3 years ago

This includes code from your macro, using the other macro for triggering purposes:

`(async () => { let defeated = canvas.tokens.placeables.filter(t => { return t.data.disposition === -1 && t.data.actorData.data?.attributes?.hp?.value <= 0 });

for (let token of defeated) {
    if (token.actor.data.type != 'npc')
        continue;

    let invalid = await token.getFlag(`world`,`lootyfied`) ? await token.getFlag(`world`,`lootyfied`) : false;
    if (invalid)
        continue;
    // Remove natural weapons, natural armor, class features, spells, and feats.
        let newItems = token.actor.data.items
          .filter((item) => {
            if (item.type == 'weapon') {
              return item.data.weaponType != 'natural';
            }
            if (item.type == 'equipment') {
              if (!item.data.armor) return true;
              return item.data.armor.type != 'natural';
            }
            return !['class', 'spell', 'feat'].includes(item.type);
          })
          .filter((item) => {
            // Determine if item is damaged
            const chanceOfDamagedItems = .25
            );
            const removeDamagedItems = .25
            );
            const damagedItemsMultiplier =.25
            );

            if (
              (item.data.rarity === 'Common' ||
              item.data.rarity === 'None') &&
              Math.random() < chanceOfDamagedItems
            ) {
              if (removeDamagedItems) return false;

              item.name += ' (Damaged)';
              item.data.price *= damagedItemsMultiplier;
            }

            return true;
          })
          .map((item) => {
            item.data.equipped = false;
            return item;
          });

        await token.actor.update({ items: [] });
        await token.actor.update({ items: newItems });

    // Change sheet to lootable, and give players permissions.

        let newActorData = {
          flags: {
            core: {
              sheetClass: 'dnd5e.LootSheet5eNPC',
            },
            lootsheetnpc5e: {
              lootsheettype: 'Loot',
            },
          },
        };

        // Handles if they already have currency set somehow
        if (typeof token.actor.data.data.currency.cp === 'number') {
          let oldCurrencyData = token.actor.data.data.currency;
          newActorData['data.currency'] = {
            cp: { value: oldCurrencyData.cp },
            ep: { value: oldCurrencyData.ep },
            gp: { value: oldCurrencyData.gp },
            pp: { value: oldCurrencyData.pp },
            sp: { value: oldCurrencyData.sp },
          };
        }
        await token.actor.update(newActorData);

        if (game.modules.get('combat-utility-belt')?.active) {
          await game.cub.removeAllConditions(token);
        }

        let lootingUsers = game.users.entries.filter((user) => {
          return (
            user.role == USER_ROLES.PLAYER ||
            user.role == USER_ROLES.TRUSTED
          );
        });
        let permissions = {};
        Object.assign(permissions, token.actor.data.permission);
        lootingUsers.forEach((user) => {
          permissions[user.data._id] = ENTITY_PERMISSIONS.OBSERVER;
        });

        await token.update({
          //overlayEffect: 'icons/svg/chest.svg',
          // effects: ['icons/containers/bags/pouch-simple-brown.webp'],
          actorData: {
            actor: {
              flags: {
                loot: {
                  playersPermission: ENTITY_PERMISSIONS.OBSERVER,
                },
              },
            },
            permission: permissions,
          },
        });
    await token.actor.update(newActorData);
    await token.setFlag(`world`,`lootyfied`,true);
}

})();`

SR5060 commented 3 years ago

sorry, new to this, not sure why the code didn't format appropriately

DFreds commented 3 years ago

No problem, I get the gist. I could definitely include a macro that does this if is it would make it easier on you. It will still require a manual trigger of the macro, though. The initial goal of this issue was to have that happen automatically. I'll include the manual version soon and look into a more automated version

SR5060 commented 3 years ago

thanks! the nice thing is that CUB can still be used to trigger the macro automatically. so CUB triggers the macro when an NPC drops to zero and then the code addition above locates the right token to transform (unless I'm missing something, that's at least how it worked for me in 7.9)

CaosFR commented 2 years ago

For your information, you can use easely this module with CUB.

Go to compendium :

Go to "Condition Lab"

It's work :)

Capture
DFreds commented 2 years ago

@CaosFR has a good answer

CaosFR commented 2 years ago

@DFreds Thanks. There is juste a little limitation. When a token are 0 hp the "Mort" triggler is ON and your macro is execute automatically. But your macro need a selected token. If they are no selected or wrong selected token it's a problem.

As you can see on the picture, I have a other macro (macro.tokenMagic.Mort) who dont have this problem. The macro it's just a preset, I dont know how tokenMagic auto-select the token. Maybe it's possible to select the target (of the triggler or the attack).

I have "code" that, maybe it's will help but can be improve :

var verifSelect = function(){
    if(canvas.tokens.controlled.length === 1 && actor.data.data.attributes.hp.value === 0) {
        const macroSupport = new game.dfreds.MacroSupport();
        macroSupport.convertSelectedTokensToLoot();
    }
    else {
        ui.notifications.error("Selectionner un token mort (5s)");
        setTimeout(verifSelect, 5000); // verifier dans 5s
    }
}
verifSelect();