conversion macro

@max.pat did you have a macro or script which could change the old classFeatures data into advancements on their items?
40 Replies
Calego
Calego•3y ago
I had one a long time ago, let me try to dig it up it definitely will need updating
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
gotchya. well if you happen upon one or anyone interested in making one, send em our way will ya?
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
this is what I had a long time ago (but definitely needs some updating):
bad code dont use, look below
bad code dont use, look below
I used this with updateAll cc @kandashi ^ for if you are interested 😉 I won't have time till this weekend probabaly to iron this out, but will do so when I can @Zhell you might be interested here too
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
I'm thinking that since the class features work is already done, we can use that format to populate class items and subclass items Basically not directly parsing the JSON you have here 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');
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');
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.
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
ohhhh nooooo did we break this with the deprecation warning?? 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
});
/**
* 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
});
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
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)
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
that looks like it works just based on my rudimentary testing
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
wtf...
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
😬
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
it's not good that I broke the other by fixing the one
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
yeah what I sent above is definitely not right its close but this is some black magic that's beyond me...
Calego
Calego•3y ago
GitLab
1.6.0 allow replacing class features entirely (#1503) · Issues · Fo...
Modules like custom classes have provided GMs a framework to replace the CONFIG.DND5E.classFeatures object entirely. The deprecation warning added in 1.6.0 broke this...
Calego
Calego•3y ago
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');
// 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');
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
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 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. @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 🙂
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
can always make a duplicate and run it on that, i do that sort of thing a lot 😛
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
Right 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. 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. 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. @alaustin this channel might be of interest to you in your quest to migrate your data
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Calego
Calego•3y ago
yeah let me put some snippets up on the repo
Calego
Calego•3y ago
@max.pat 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.
GitLab
1.6.1 Subclass Compendium Item Creation ($2313873) · Snippets · Fou...
An implementation of the Dungeons & Dragons 5th Edition game system for Foundry Virtual Tabletop (http://foundryvtt.com). This work is permitted under the Open...
GitLab
1.6.1 Class Compendium Migration ($2313875) · Snippets · Foundry Ne...
An implementation of the Dungeons & Dragons 5th Edition game system for Foundry Virtual Tabletop (http://foundryvtt.com). This work is permitted under the Open...
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Leo The League Lion
Leo The League Lion•3y ago
@max.pat gave vote LeaguePoints™ to @calego (#1 • 1495)
Zhell
Zhell•3y ago
I dunno if there is any interest but I made a conversion macro of my own of sorts using regex that takes any subclass item and creates the features and advancement as long as it's written in the right formatting, i.e., in the likeness of dndbeyond:
<p>subclass description goes here</p>
<h2>feature name</h2>
<p><em>xth-level subclassName feature</em></p>
<p>feature description...</p>
<h2> etc etc
<p>subclass description goes here</p>
<h2>feature name</h2>
<p><em>xth-level subclassName feature</em></p>
<p>feature description...</p>
<h2> etc etc
It sets up the feature's description.value, the advancement in the subclass, the requirement on the features and slaps them all in a compendium.
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Zhell
Zhell•3y ago
oh shoot, lemme see if I still have it
Zhell
Zhell•3y ago
I think this was it, I got a few.
Unknown User
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Leo The League Lion
Leo The League Lion•3y ago
@max.pat gave vote LeaguePoints™ to @Zhell (#200 • 3)