conversion macro

CCalego4/27/2022
@MaxPat did you have a macro or script which could change the old classFeatures data into advancements on their items?
CCalego4/27/2022
I had one a long time ago, let me try to dig it up
CCalego4/27/2022
it definitely will need updating
UUUnknown User4/27/2022
Message Not Public
Sign In & Join Server To View
CCalego4/27/2022
gotchya. well if you happen upon one or anyone interested in making one, send em our way will ya?
UUUnknown User4/27/2022
Message Not Public
Sign In & Join Server To View
CCalego4/27/2022
this is what I had a long time ago (but definitely needs some updating):
bad code dont use, look below

I used this with updateAll
CCalego4/27/2022
cc @🌈 Kandashi 🌈 (He/Him) ^ for if you are interested 😉
CCalego4/27/2022
I won't have time till this weekend probabaly to iron this out, but will do so when I can
CCalego4/27/2022
@Zhell you might be interested here too
UUUnknown User4/27/2022
Message Not Public
Sign In & Join Server To View
CCalego4/27/2022
I'm thinking that since the class features work is already done, we can use that format to populate class items and subclass items
CCalego4/27/2022
Basically not directly parsing the JSON you have here
CCalego4/27/2022
Macro runnable snippet which will take an existing compendium with Class Items, and update that compendium's items with advancements as defined in the deprecated CONFIG.DND5E.classFeatures (useful for some modules which overrode or extended this).

const PACK_NAME = 'world.blank-class-items';
/* Update All Class Items in the Compendium per legacy CONFIG.DND5E.classFeatures */
/* v0.3 */
const pack = game.packs.get(PACK_NAME);

if (!pack) {
  ui.notifications.error('No pack by that name');
  return;
};

const docs = await pack.getDocuments();

for (let item of docs) {
  const className = item.name.slugify({strict: true});
  const clsConfig = CONFIG.DND5E.classFeatures[className];
  if (!clsConfig) continue;

  const advancements = Object.entries(clsConfig.features).map(([level, items]) => {
    return {
      classRestriction: "",
      level,
      icon: "",
      type: 'ItemGrant',
      title: "Features",
      configuration: { items },
      value: {},
      _id: foundry.utils.randomID(),
    }
  });

  // add hitpoints advancement because this is a class
  advancements.push({
      classRestriction: "",
      type: "HitPoints",
      icon: "",
      title: "",
      configuration: {},
      value: {},
      _id: foundry.utils.randomID(),
  });

  await item.update({
    'data.advancement': advancements
  });
}

pack.render(true);
ui.notifications.notify('Complete');
CCalego4/27/2022
A class compendium migration script for your guys' perusal and testing.

Gonna work on one that creates a compendium for subclasses next as I have time.
Then one which attempts to migrate an existing actor.
UUUnknown User4/27/2022
2 Messages Not Public
Sign In & Join Server To View
CCalego4/28/2022
ohhhh nooooo
CCalego4/28/2022
did we break this with the deprecation warning??
CCalego4/28/2022
If you have this locally, can you test something for me?

In config.js in the 5e repo files, change the classFeatures block to be this
/**
 * Character features automatically granted by classes & subclasses at certain levels.
 * @type {object}
 */
Object.defineProperty(DND5E, "classFeatures", {
  _classFeatures: ClassFeatures,
  get() {
    console.warn(
      "The classFeatures object is deprecated. Please use the new Advancement API to configure class features.");
    return this._classFeatures;
  },
  set(newClassFeatures) {
    this._classFeatures = newClassFeatures;
  },
  configurable: true,
  enumerable: true
});
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
that would be because they're setting something nested within the object I guess.
You look to be replacing the object itself (which should still be supported and hopefully my snippet will allow that)
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
that looks like it works just based on my rudimentary testing
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
wtf...
UUUnknown User4/28/2022
2 Messages Not Public
Sign In & Join Server To View
CCalego4/28/2022
😬
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
it's not good that I broke the other by fixing the one
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
yeah what I sent above is definitely not right
CCalego4/28/2022
its close but this is some black magic that's beyond me...
CCalego4/28/2022
Macro runnable snippet which will take an existing compendium and create subclasses in that compendium with advancements as defined in the deprecated CONFIG.DND5E.classFeatures (useful for some modules which overrode or extended this, in theory).

Will not create duplicates (determined by name). Optionally allows creation of "empty" subclasses which have no features defined (core 5e lists a lot of RAW subclasses without features).

// the compendium id which should have the subclasses added to it
const PACK_NAME = 'world.custom-subclasses';

// the core system includes subclasses without features defined, should these be created as subclasses?
const INCLUDE_EMPTY_SUBCLASSES = false;

/* Create Subclass Items that are missing (based on name matching) in the Compendium per legacy CONFIG.DND5E.classFeatures */
/* v0.1 */
const pack = game.packs.get(PACK_NAME);

if (!pack) {
  ui.notifications.error('No pack by that name');
  return;
};

const itemData = Object.entries(CONFIG.DND5E.classFeatures).map(([classIdentifier, { subclasses }]) => {
  const subclassItemData = Object.entries(subclasses).map(([subclassIdentifier, { label, features, source }]) => {
    if (!INCLUDE_EMPTY_SUBCLASSES && (!features || foundry.utils.isObjectEmpty(features))) return;

    const advancements = (!features || foundry.utils.isObjectEmpty(features)) ? [] : Object.entries(features).map(([level, items]) => {
      return {
        classRestriction: "",
        level,
        icon: "",
        type: 'ItemGrant',
        title: "Features",
        configuration: { items },
        value: {},
        _id: foundry.utils.randomID(),
      }
    });

    return {
      data: {
        advancement: advancements,
        identifier: subclassIdentifier,
        classIdentifier,
        source,
      },
      name: label,
      type: 'subclass'
    }
  });

  return subclassItemData;

}).flat().filter(Boolean).filter(({name}) => !pack.index.getName(name));

console.log("Creating Items:", itemData);
await Item.implementation.create(itemData, { pack: PACK_NAME });

pack.render(true);
ui.notifications.notify('Complete');
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
OK THIS ONES GNARLY.

This is 0.1 for a macro script which will migrate an actor to use class advancement which doesn't currently.

It makes some assumptions:
1. The class item being used has a core.sourceId flag (happens when you drag/drop from a compendium/world item).
2. That original class item has been updated to have advancements.
3. Those advancements reference the same items as were manually added to the actor before.
https://gist.github.com/akrigline/170159bf376969b69c25a62f97398982#file-migrate-actor-js
migrate-actor.js in the gist
CCalego4/28/2022
I was able to use this on a 1.5.x "Starter Hero" (Quillathe) to introduce advancements to them in 1.6.x

Haven't gotten my head wrapped around adding a subclass item automatically yet and am too tired to try that tonight, but it's on the todo for this bad boy.
CCalego4/28/2022
@unsoluble this one might interest you, try at your own risk 😛
Obviously not ready for sharing at large but you expressed interest on the mothership so now I'm pulling you in here 🙂
UUUnknown User4/28/2022
2 Messages Not Public
Sign In & Join Server To View
CCalego4/28/2022
can always make a duplicate and run it on that, i do that sort of thing a lot 😛
UUUnknown User4/28/2022
Message Not Public
Sign In & Join Server To View
CCalego4/28/2022
Right
CCalego4/28/2022
Well, kinda.

It will try to configure the actor as though it has been getting advancements the whole time getting the class item that was added to the actor originally.
CCalego4/28/2022
It nukes any hp advancements because idk how I could figure out that info to backfill.

But it will look at the item grants and try to match up existing items on the actor with items they should have been granted if they had gone through the advancement flows.

This does not back fill items "missing" from the advancement, it assumes more or less that the actor is currently configured well, but wants to use advancement going forwards.
CCalego4/28/2022
For any level lower than the current level of that class, it turns the item grant advancement into an optional one; then updates items with the flag to make it appear they are from an advancement.
CCalego4/28/2022
@alaustin this channel might be of interest to you in your quest to migrate your data
UUUnknown User5/12/2022
2 Messages Not Public
Sign In & Join Server To View
CCalego5/12/2022
yeah let me put some snippets up on the repo
CCalego5/12/2022
@MaxPat
https://gitlab.com/foundrynet/dnd5e/-/snippets/2313873
https://gitlab.com/foundrynet/dnd5e/-/snippets/2313875
all yours :P.
I'll try to post something about them in the mothership today, but i've not been good about self-imposed timers lately.
UUUnknown User5/12/2022
Message Not Public
Sign In & Join Server To View
LTLLLeo The League Lion5/12/2022
@MaxPat gave :vote: LeaguePoints™ to @Calego (ElfFriend) (#1 • 1495)
UUUnknown User6/15/2022
6 Messages Not Public
Sign In & Join Server To View
LTLLLeo The League Lion6/15/2022
@MaxPat gave :vote: LeaguePoints™ to @Zhell (#200 • 3)