foundryvtt / dnd5e

An implementation of the 5th Edition game system for Foundry Virtual Tabletop (http://foundryvtt.com).
MIT License
333 stars 222 forks source link

SRD inconsistencies and automatic structuration of documents #1432

Closed aaclayton closed 3 weeks ago

aaclayton commented 2 years ago

Originally in GitLab by @playest

I have a found a few inconsistencies in the JSON files of the SRD:

I have found these "inconsistencies" because I was trying to automatically recreate the same architecture and sort my documents for my custom compendium (for my "house" games) than the one used here. At first it was quite easy because you could just use the type field (and the consumableType field when present). But when you start managing feats it get complicated.

Here is what I achieved so far:

function computePath(doc: FoundryVtt.Document) {
    if(!("type" in doc)) {
        return "rules";
    }
    else if(doc.type == "character") {
        return "heroes";
    }
    else if(doc.type == "weapon") {
        return Path.join("items", "weapon");
    }
    else if(doc.type == "tool") {
        return Path.join("items", "tool");
    }
    else if(doc.type == "equipment") {
        return Path.join("items", "equipment");
    }
    else if(doc.type == "backpack") {
        return Path.join("items", "backpack");
    }
    else if(doc.type == "class") {
        return "classes";
    }
    else if(doc.type == "feat") {
        if(isRace(doc.name)) {
            return "races";
        }
        else if(doc.data?.requirements === "") {
            return "monsterfeatures";
        }
        else if(doc.data?.requirements) {
            const requirementsField = doc.data?.requirements;
            const requirements = splitRequirements(requirementsField);
            const intersectionForClass = requirements.filter(r => isClass(r.thing));
            if(intersectionForClass.length >= 1) {
                return "classfeatures";
            }

            const intersectionForRace = requirements.filter(r => isRace(r.thing));
            if(intersectionForRace.length >= 1) {
                return "races";
            }

            const intersectionForSubclasses = requirements.filter(r => isSubclass(r.thing));
            if(intersectionForSubclasses.length >= 1) {
                return "classfeatures";
            }

            const intersectionForSubrace = requirements.filter(r => isSubrace(r.thing));
            if(intersectionForSubrace.length >= 1) {
                return "races";
            }

            const intersectionForMonsters = requirements.filter(r => isMonster(r.thing));
            if(intersectionForMonsters.length >= 1) {
                return "monsterfeatures";
            }
            else {
                console.log(splitRequirements(requirementsField));
            }
        }
    }
    else if(doc.type == "npc") {
        return Path.join("monsters", doc.data?.details?.type?.value ?? "");
    }
    else if(doc.type == "spell") {
        if(doc.data?.level === 0) {
            return Path.join("spells", "cantrip");
        }
        else {
            return Path.join("spells", "level-" + doc.data?.level);
        }
    }
    else if(doc.type == "consumable") {
        return Path.join("items", doc.data?.consumableType ?? "");
    }
    else if(doc.type == "loot") {
        if(isTradeGood(doc.name)) {
            return "tradegoods";
        }
        else {
            return Path.join("items", "loot");
        }
    }
    return null;
}

I had to hardcode the isClass, isRace, isSubclass, isSubrace and isMonster functions because I don't think I can reliably deduce that from the JSON. Is there any plan to make these deductions possible? Maybe we could use the "folder" field? Or add some kind of type in "flags" field?

aaclayton commented 2 years ago

Originally in GitLab by @playest

That would definitely solve part of the problem (only a part of it because it couldn't solve how to differentiate trade goods from other loot for example).

Also the #1348 seems to be related to information you can access in-game (which would obviously be better) whereas my proposal was kind of targeting tools and developers.

aaclayton commented 2 years ago

Originally in GitLab by @arbron

For adding subcategories to feature types, there is another issue here: https://gitlab.com/foundrynet/dnd5e/-/issues/1348

aaclayton commented 2 years ago

Originally in GitLab by @playest

I notices that the claw-attack was legendary. Maybe that is why it's not a weapon?

Any way, the fact that bite is the ONLY weapon in "monsterfeatures" is weird.

aaclayton commented 2 years ago

Originally in GitLab by @playest

It might be useful to know, for example, if a given Bite feature is the monster one, or if it's the Lizardfolk racial Bite feature, I'm not sure though.

I agree. I'll try to think about a good way to do it and propose something. I'm thinking about taking advantage of the clean job (in packs.js) to remove it from the built compendium. Or maybe we want to keep it even in the compendium?

aaclayton commented 2 years ago

Originally in GitLab by @Fyorl

And what about the inconsistencies from the beginning of my post? Would you accept a MR that fixes them?

Yes, any work to tidy up existing compendium content is welcome, I think. It looks like the Bite attack is the one that's potentially in error as this is supposed to be a generic monster feature rather than one that has specific to hit and damage values. I'd have to check some of the others to be sure though.

Similarly, would you accept a MR that makes a distinction between class features, racial features, and monster features (and maybe other stuff, like trade goods) so that it is not manual anymore?

This one is more difficult. There might be room in the data model to provide some sort of category for a feature. It might be useful to know, for example, if a given Bite feature is the monster one, or if it's the Lizardfolk racial Bite feature, I'm not sure though.

aaclayton commented 2 years ago

Originally in GitLab by @playest

And what about the inconsistencies from the beginning of my post? Would you accept a MR that fixes them?

Similarly, would you accept a MR that makes a distinction between class features, racial features, and monster features (and maybe other stuff, like trade goods) so that it is not manual anymore?

aaclayton commented 2 years ago

Originally in GitLab by @Fyorl

There are no plans after that fashion, no. We don't currently make any distinction, in the data, between a class feature and a subclass feature, or a racial vs. a subrace feature. Similarly the categorisation between class features, racial features, and monster features has been done manually by placing them in separate compendia.