Exemple #1
0
def parseMonster(m, compendium, args):
    if '_copy' in m:
        if args.verbose:
            print("COPY: " + m['name'] + " from " + m['_copy']['name'] +
                  " in " + m['_copy']['source'])
        xtrsrc = "./data/bestiary/bestiary-" + m['_copy']['source'].lower(
        ) + ".json"
        try:
            with open(xtrsrc, encoding='utf-8') as f:
                d = json.load(f)
                f.close()
            mcpy = copy.deepcopy(m)
            for mn in d['monster']:
                if mn['name'].lower() == mcpy['_copy']['name'].lower():
                    if '_copy' in mn:
                        if args.verbose:
                            print("ANOTHER COPY: " + mn['name'] + " from " +
                                  mn['_copy']['name'] + " in " +
                                  mn['_copy']['source'])
                        xtrsrc2 = "./data/bestiary/bestiary-" + mn['_copy'][
                            'source'].lower() + ".json"
                        with open(xtrsrc2, encoding='utf-8') as f:
                            d2 = json.load(f)
                            f.close()
                        for mn2 in d2['monster']:
                            if mn2['name'] == mn['_copy']['name']:
                                mn = copy.deepcopy(mn2)
                                break
                    m = copy.deepcopy(mn)
                    m['name'] = mcpy['name']
                    if 'isNpc' in mcpy:
                        m['isNpc'] = mcpy['isNpc']
                    m['source'] = mcpy['source']
                    if "otherSources" in mcpy:
                        m["otherSources"] = mcpy["otherSources"]
                    elif "otherSources" in m:
                        del m["otherSources"]
                    if 'size' in mcpy:
                        m['size'] = mcpy['size']
                    if 'hp' in mcpy:
                        m['hp'] = mcpy['hp']
                    if 'original_name' in mcpy:
                        m['original_name'] = mcpy['original_name']
                    if 'page' in mcpy:
                        m['page'] = mcpy['page']
                    elif 'page' in m:
                        del m['page']
                    if 'image' in mcpy:
                        m['image'] = mcpy['image']
                    if '_mod' in mcpy['_copy']:
                        m = utils.modifyMonster(m, mcpy['_copy']['_mod'])
                    break
            if '_trait' in mcpy['_copy']:
                if args.verbose:
                    print("Adding extra traits for: " +
                          mcpy['_copy']['_trait']['name'])
                traits = "./data/bestiary/traits.json"
                with open(traits, encoding='utf-8') as f:
                    d = json.load(f)
                    f.close()
                for trait in d['trait']:
                    if trait['name'] == mcpy['_copy']['_trait']['name']:
                        if '_mod' in trait['apply']:
                            m = utils.modifyMonster(m, trait['apply']['_mod'])
                        if '_root' in trait['apply']:
                            for key in trait['apply']['_root']:
                                if key == "speed" and type(
                                        trait['apply']['_root'][key]) == int:
                                    for k2 in m['speed']:
                                        m['speed'][k2] = trait['apply'][
                                            '_root'][key]
                                else:
                                    m[key] = trait['apply']['_root'][key]
        except IOError as e:
            if args.verbose:
                print("Could not load additional source ({}): {}".format(
                    e.errno, e.strerror))
            return
#    for eachmonsters in compendium.findall('monster'):
#        if eachmonsters.find('name').text == m['name']:
#            m['name'] = "{} (DUPLICATE IN {})".format(m['name'],m['source'])
    monster = ET.SubElement(compendium, 'monster')
    id = ET.SubElement(monster, 'id')
    id.text = m['source'].lower() + "-" + re.sub(r'\W+', '', m['name']).lower()

    name = ET.SubElement(monster, 'name')
    name.text = m['name']

    size = ET.SubElement(monster, 'size')
    size.text = m['size']

    typ = ET.SubElement(monster, 'type')
    if isinstance(m['type'], dict):
        if 'swarmSize' in m['type']:
            typ.text = "swarm of {} {}s".format(utils.convertSize(m['size']),
                                                m['type']['type'])
        elif 'tags' in m['type']:
            subtypes = []
            for tag in m['type']['tags']:
                if not isinstance(tag, dict):
                    subtypes.append(tag)
                else:
                    subtypes.append(tag['prefix'] + tag['tag'])
            typ.text = "{} ({})".format(m['type']['type'], ", ".join(subtypes))
        else:
            typ.text = m['type']['type']
    else:
        typ.text = m['type']

    alignment = ET.SubElement(monster, 'alignment')
    if 'alignment' not in m:
        m['alignment'] = ['A']
    alignment.text = utils.convertAlignList(m['alignment'])

    ac = ET.SubElement(monster, 'ac')
    acstr = []
    for acs in m['ac']:
        if isinstance(acs, dict):
            if len(acstr) == 0:
                if 'ac' in acs:
                    acstr.append(str(acs['ac']))
                if 'from' in acs and 'condition' in acs:
                    acstr.append(
                        utils.fixTags(
                            ", ".join(acs['from']) + " " + acs['condition'], m,
                            True))
                elif 'from' in acs:
                    acstr.append(utils.fixTags(", ".join(acs['from']), m,
                                               True))
                elif 'condition' in acs:
                    acstr.append(utils.fixTags(acs['condition'], m, True))
                if 'special' in acs:
                    acstr.append(utils.fixTags(acs['special'], m, True))
                continue
            acstr.append(
                utils.fixTags(
                    "{}".format("{} {}".format(
                        acs['ac'], "(" + ", ".join(acs['from']) + ") " +
                        acs['condition'] if 'from' in acs and 'condition' in
                        acs else "(" + ", ".join(acs['from']) +
                        ")" if 'from' in acs else acs['condition']
                    ) if 'from' in acs or 'condition' in acs else acs['ac']),
                    m, True))
        else:
            acstr.append(str(acs))
    if len(acstr) > 1:
        ac.text = "{} ({})".format(acstr[0], ", ".join(acstr[1:]))
    elif acstr[0]:
        ac.text = acstr[0]
    else:
        ac.text = "0"

    hp = ET.SubElement(monster, 'hp')
    if "special" in m['hp']:
        if args.nohtml and re.match(r'equal the .*?\'s Constitution modifier',
                                    m['hp']['special']):
            hp.text = str(utils.getAbilityMod(m['con']))
            if 'trait' in m:
                m['trait'].insert(0, {
                    "name": "Hit Points",
                    "entries": [m['hp']['special']]
                })
            else:
                m['trait'] = [{
                    "name": "Hit Points",
                    "entries": [m['hp']['special']]
                }]
        elif args.nohtml:
            hpmatch = re.match(
                r'[0-9]+ ?(\([0-9]+[Dd][0-9]+( ?\+ ?[0-9]+)?\))?',
                m['hp']['special'])
            if hpmatch:
                hp.text = str(hpmatch.group(0)).rstrip()
            else:
                hp.text = "0"
            if 'trait' in m:
                m['trait'].insert(0, {
                    "name": "Hit Points",
                    "entries": [m['hp']['special']]
                })
            else:
                m['trait'] = [{
                    "name": "Hit Points",
                    "entries": [m['hp']['special']]
                }]
        else:
            hp.text = m['hp']['special']
    else:
        hp.text = "{} ({})".format(m['hp']['average'],
                                   m['hp']['formula'].replace(' ', ''))

    speed = ET.SubElement(monster, 'speed')
    if type(m['speed']) == str:
        speed.text = m['speed']
    elif 'choose' in m['speed']:
        lis = []
        for key, value in m['speed'].items():
            if key == "walk":
                lis.append("walk " + str(value) + " ft.")
            elif key == "choose":
                value['from'].insert(-1, 'or')
                lis.append("{} {} ft. {}".format(" ".join(value['from']),
                                                 value['amount'],
                                                 value['note']))
            else:
                lis.append("{} {} ft.".format(key, value))
        speed.text = ", ".join(lis)
    else:
        speed.text = ", ".join([
            "{} {} ft.".format(
                key, value['number'] if isinstance(value, dict) else value)
            for key, value in m['speed'].items()
            if not isinstance(value, bool)
        ])

    statstr = ET.SubElement(monster, 'str')
    statstr.text = str(m['str'] if 'str' in m else '0')
    statdex = ET.SubElement(monster, 'dex')
    statdex.text = str(m['dex'] if 'dex' in m else '0')
    statcon = ET.SubElement(monster, 'con')
    statcon.text = str(m['con'] if 'con' in m else '0')
    statint = ET.SubElement(monster, 'int')
    statint.text = str(m['int'] if 'int' in m else '0')
    statwis = ET.SubElement(monster, 'wis')
    statwis.text = str(m['wis'] if 'wis' in m else '0')
    statcha = ET.SubElement(monster, 'cha')
    statcha.text = str(m['cha'] if 'cha' in m else '0')
    if 'isNpc' in m and m['isNpc'] and not args.nohtml:
        npcroll = ET.SubElement(monster, 'role')
        npcroll.text = "ally"
    save = ET.SubElement(monster, 'save')
    savelist = ET.SubElement(monster, 'savelist')

    if 'save' in m:
        savestr = ET.SubElement(savelist, 'str')
        savestr.text = m['save'].get('str', '')
        savedex = ET.SubElement(savelist, 'dex')
        savedex.text = m['save'].get('dex', '')
        savecon = ET.SubElement(savelist, 'con')
        savecon.text = m['save'].get('con', '')
        saveint = ET.SubElement(savelist, 'int')
        saveint.text = m['save'].get('int', '')
        savewis = ET.SubElement(savelist, 'wis')
        savewis.text = m['save'].get('wis', '')
        savecha = ET.SubElement(savelist, 'cha')
        savecha.text = m['save'].get('cha', '')

    if 'save' in m:
        save.text = ", ".join([
            "{} {}".format(str.capitalize(key), value)
            for key, value in m['save'].items()
        ])

    skill = ET.SubElement(monster, 'skill')
    if 'skill' in m:
        skills = []
        for key, value in m['skill'].items():
            if type(value) == str:
                skills.append("{} {}".format(str.capitalize(key), value))
            else:
                if key == "other":
                    for sk in value:
                        if "oneOf" in sk:
                            if args.nohtml:
                                if 'trait' not in m: m['trait'] = []
                                m['trait'].insert(
                                    0, {
                                        "name":
                                        "Skills",
                                        "entries": [
                                            "plus one of the following: " +
                                            ", ".join([
                                                "{} {}".format(
                                                    str.capitalize(ook), oov)
                                                for ook, oov in
                                                sk["oneOf"].items()
                                            ])
                                        ]
                                    })
                            else:
                                skills.append(
                                    "plus one of the following: " + ", ".join([
                                        "{} {}".format(str.capitalize(ook),
                                                       oov)
                                        for ook, oov in sk["oneOf"].items()
                                    ]))
        skill.text = ", ".join(skills)

    if 'passive' in m:
        passive = ET.SubElement(monster, 'passive')
        passive.text = str(m['passive'])

    languages = ET.SubElement(monster, 'languages')
    if 'languages' in m:
        languages.text = ", ".join([x for x in m['languages']])

    cr = ET.SubElement(monster, 'cr')
    if 'cr' in m:
        if isinstance(m['cr'], dict):
            cr.text = str(m['cr']['cr'])
        else:
            if not m['cr'] == "Unknown":
                cr.text = str(m['cr'])

    resist = ET.SubElement(monster, 'resist')
    if 'resist' in m:
        resistlist = utils.parseRIV(m, 'resist')
        resist.text = ", ".join(resistlist)

    immune = ET.SubElement(monster, 'immune')
    if 'immune' in m:
        immunelist = utils.parseRIV(m, 'immune')
        immune.text = ", ".join(immunelist)

    vulnerable = ET.SubElement(monster, 'vulnerable')
    if 'vulnerable' in m:
        vulnerablelist = utils.parseRIV(m, 'vulnerable')
        vulnerable.text = ", ".join(vulnerablelist)

    conditionImmune = ET.SubElement(monster, 'conditionImmune')
    if 'conditionImmune' in m:
        conditionImmunelist = utils.parseRIV(m, 'conditionImmune')
        conditionImmune.text = ", ".join(conditionImmunelist)

    senses = ET.SubElement(monster, 'senses')
    if 'senses' in m:
        senses.text = ", ".join([x for x in m['senses']])

    if 'source' in m and not args.srd:
        slug = slugify(m["name"])
        if args.addimgs and os.path.isdir("img") and not os.path.isfile(
                os.path.join(args.tempdir, "monsters", slug + ".png")
        ) and not os.path.isfile(
                os.path.join(args.tempdir, "monsters", slug + ".jpg")
        ) and not os.path.isfile(
                os.path.join(args.tempdir, "monsters",
                             "token_" + slug + ".png")) and not os.path.isfile(
                                 os.path.join(args.tempdir, "monsters",
                                              "token_" + slug + ".jpg")):
            if not os.path.isdir(os.path.join(args.tempdir, "monsters")):
                os.mkdir(os.path.join(args.tempdir, "monsters"))
            #if not os.path.isdir(os.path.join(args.tempdir,"tokens")):
            #    os.mkdir(os.path.join(args.tempdir,"tokens"))
            if 'image' in m:
                artworkpath = m['image']
            else:
                artworkpath = None
            monstername = m["original_name"] if "original_name" in m else m[
                "name"]
            if artworkpath and os.path.isfile("./img/" + artworkpath):
                artworkpath = "./img/" + artworkpath
            elif os.path.isfile("./img/bestiary/" + m["source"] + "/" +
                                monstername + ".jpg"):
                artworkpath = "./img/bestiary/" + m[
                    "source"] + "/" + monstername + ".jpg"
            elif os.path.isfile("./img/bestiary/" + m["source"] + "/" +
                                monstername + ".png"):
                artworkpath = "./img/bestiary/" + m[
                    "source"] + "/" + monstername + ".png"
            elif os.path.isfile("./img/vehicles/" + m["source"] + "/" +
                                monstername + ".jpg"):
                artworkpath = "./img/vehicles/" + m[
                    "source"] + "/" + monstername + ".jpg"
            elif os.path.isfile("./img/vehicles/" + m["source"] + "/" +
                                monstername + ".png"):
                artworkpath = "./img/vehicles/" + m[
                    "source"] + "/" + monstername + ".png"
            if artworkpath is not None:
                ext = os.path.splitext(artworkpath)[1]
                copyfile(artworkpath,
                         os.path.join(args.tempdir, "monsters", slug + ext))
                imagetag = ET.SubElement(monster, 'image')
                imagetag.text = slug + ext
            if os.path.isfile("./img/" + m["source"] + "/" + monstername +
                              ".png") or os.path.isfile("./img/" +
                                                        m["source"] + "/" +
                                                        monstername + ".jpg"):
                if os.path.isfile("./img/" + m["source"] + "/" + monstername +
                                  ".png"):
                    artworkpath = "./img/" + m[
                        "source"] + "/" + monstername + ".png"
                else:
                    artworkpath = "./img/" + m[
                        "source"] + "/" + monstername + ".jpg"
                ext = os.path.splitext(artworkpath)[1]
                copyfile(
                    artworkpath,
                    os.path.join(args.tempdir, "monsters",
                                 "token_" + slug + ext))
                imagetag = ET.SubElement(monster, 'token')
                imagetag.text = slug + ext
            elif os.path.isfile("./img/vehicles/tokens/" + m["source"] + "/" +
                                monstername + ".png") or os.path.isfile(
                                    "./img/vehicles/tokens/" + m["source"] +
                                    "/" + monstername + ".jpg"):
                if os.path.isfile("./img/vehicles/tokens/" + m["source"] +
                                  "/" + monstername + ".png"):
                    artworkpath = "./img/vehicles/tokens/" + m[
                        "source"] + "/" + monstername + ".png"
                else:
                    artworkpath = "./img/vehicles/tokens/" + m[
                        "source"] + "/" + monstername + ".jpg"
                ext = os.path.splitext(artworkpath)[1]
                copyfile(
                    artworkpath,
                    os.path.join(args.tempdir, "monsters",
                                 "token_" + slug + ext))
                imagetag = ET.SubElement(monster, 'token')
                imagetag.text = "token_" + slug + ext
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "monsters", slug + ".png")):
            imagetag = ET.SubElement(monster, 'image')
            imagetag.text = slug + ".png"
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "monsters", slug + ".jpg")):
            imagetag = ET.SubElement(monster, 'image')
            imagetag.text = slug + ".jpg"
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "monsters",
                             "token_" + slug + ".png")):
            imagetag = ET.SubElement(monster, 'token')
            imagetag.text = "token_" + slug + ".png"
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "monsters",
                             "token_" + slug + ".jpg")):
            imagetag = ET.SubElement(monster, 'token')
            imagetag.text = "token_" + slug + ".jpg"
        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source'], args), m['page']
        ) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(
            m['source'], args)

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                if "source" not in s:
                    continue
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"], args),
                    s["page"]) if 'page' in s and s[
                        "page"] != 0 else utils.getFriendlySource(
                            s["source"], args)
        #trait = ET.SubElement(monster, 'trait')
        #name = ET.SubElement(trait, 'name')
        #name.text = "Source"
        #text = ET.SubElement(trait, 'text')
        #text.text = sourcetext
        if not args.nohtml:
            srctag = ET.SubElement(monster, 'source')
            srctag.text = sourcetext
    else:
        sourcetext = None

    if 'trait' in m:
        for t in m['trait']:
            trait = ET.SubElement(monster, 'trait')
            name = ET.SubElement(trait, 'name')
            name.text = utils.remove5eShit(t['name'])
            if "entries" not in t:
                t["entries"] = []
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(trait, 'text')
                text.text = e

    if 'action' in m and m['action'] is not None:
        for t in m['action']:
            action = ET.SubElement(monster, 'action')
            if 'name' in t:
                name = ET.SubElement(action, 'name')
                name.text = utils.remove5eShit(t['name'])
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(action, 'text')
                text.text = e
                for match in re.finditer(
                        r'(((\+|\-)?[0-9]*) to hit.*?|DC [0-9]+ .*? saving throw.*?)\(([0-9Dd\+\- ]+)\) .*? damage',
                        e):
                    if match.group(4):
                        attack = ET.SubElement(action, 'attack')
                        attack.text = "{}|{}|{}".format(
                            utils.remove5eShit(t['name'])
                            if 'name' in t else "",
                            match.group(2).replace(' ', '')
                            if match.group(2) else "",
                            match.group(4).replace(' ', ''))

    if 'reaction' in m and m['reaction'] is not None:
        for t in m['reaction']:
            action = ET.SubElement(monster, 'reaction')
            name = ET.SubElement(action, 'name')
            name.text = utils.remove5eShit(t['name'])
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(action, 'text')
                text.text = e

    if 'variant' in m and m['variant'] is not None:
        if type(m['variant']) != list:
            m['variant'] = [m['variant']]
        for t in m['variant']:
            action = ET.SubElement(monster, 'action')
            name = ET.SubElement(action, 'name')
            name.text = "Variant: " + utils.remove5eShit(t['name'])
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(action, 'text')
                text.text = e

    if 'legendary' in m:
        legendary = ET.SubElement(monster, 'legendary')

        if "legendaryHeader" in m:
            for h in m['legendaryHeader']:
                text = ET.SubElement(legendary, 'text')
                text.text = utils.remove5eShit(h)
        else:
            text = ET.SubElement(legendary, 'text')
            if "isNamedCreature" in m and m['isNamedCreature']:
                text.text = "{0} can take {1:d} legendary action{2}, choosing from the options below. Only one legendary action can be used at a time and only at the end of another creature's turn. {0} regains spent legendary action{2} at the start of its turn.".format(
                    m['name'].split(' ', 1)[0], len(m['legendary']),
                    "s" if len(m['legendary']) > 1 else "")
            else:
                text.text = "The {0} can take {1:d} legendary action{2}, choosing from the options below. Only one legendary action can be used at a time and only at the end of another creature's turn. The {0} regains spent legendary action{2} at the start of its turn.".format(
                    m['type'] if type(m['type']) == str else "{} ({})".format(
                        m['type']['type'], ", ".join(m['type']['tags']))
                    if 'tags' in m['type'] else m['type']['type'],
                    len(m['legendary']),
                    "s" if len(m['legendary']) > 1 else "")
        for t in m['legendary']:
            legendary = ET.SubElement(monster, 'legendary')
            name = ET.SubElement(legendary, 'name')
            if 'name' not in t:
                t['name'] = ""
            name.text = utils.remove5eShit(t['name'])
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(legendary, 'text')
                text.text = e

    if 'mythic' in m:
        mythic = ET.SubElement(monster, 'legendary')

        if "mythicHeader" in m:
            for h in m['mythicHeader']:
                name = ET.SubElement(mythic, 'name')
                name.text = "Mythic Actions"
                mythic = ET.SubElement(monster, 'legendary')
                text = ET.SubElement(mythic, 'text')
                text.text = utils.remove5eShit(h)
        for t in m['mythic']:
            mythic = ET.SubElement(monster, 'legendary')
            name = ET.SubElement(mythic, 'name')
            if 'name' not in t:
                t['name'] = ""
            name.text = utils.remove5eShit(t['name'])
            for e in utils.getEntryString(t["entries"], m, args).split("\n"):
                text = ET.SubElement(mythic, "text")
                text.text = e

    if 'legendaryGroup' in m:
        with open("./data/bestiary/legendarygroups.json",
                  encoding='utf-8') as f:
            meta = json.load(f)
            f.close()
        for l in meta['legendaryGroup']:
            if l['name'] != m['legendaryGroup']['name']:
                continue
            if 'lairActions' in l:
                legendary = ET.SubElement(monster, 'legendary')
                name = ET.SubElement(legendary, 'name')
                name.text = "Lair Actions"
                legendary = ET.SubElement(monster, 'legendary')
                for t in l['lairActions']:
                    if type(t) == str:
                        text = ET.SubElement(legendary, 'text')
                        text.text = utils.fixTags(t, m, args.nohtml)
                        continue
                    if 'name' in t:
                        name = ET.SubElement(legendary, 'name')
                        name.text = "Lair Action: " + utils.remove5eShit(
                            t['name'])
                    if t['type'] == 'list':
                        for i in t['items']:
                            text = ET.SubElement(legendary, 'text')
                            text.text = "• " + utils.fixTags(i, m, args.nohtml)
                        continue
                    for e in utils.getEntryString(t["entries"], m,
                                                  args).split("\n"):
                        text = ET.SubElement(legendary, 'text')
                        text.text = e

            if 'regionalEffects' in l:
                legendary = ET.SubElement(monster, 'legendary')
                name = ET.SubElement(legendary, 'name')
                name.text = "Regional Effects"
                legendary = ET.SubElement(monster, 'legendary')
                for t in l['regionalEffects']:
                    if type(t) == str:
                        text = ET.SubElement(legendary, 'text')
                        text.text = utils.fixTags(t, m, args.nohtml)
                        continue
                    if 'name' in t:
                        name = ET.SubElement(legendary, 'name')
                        name.text = "Regional Effect: " + utils.remove5eShit(
                            t['name'])
                    if t['type'] == 'list':
                        for i in t['items']:
                            text = ET.SubElement(legendary, 'text')
                            text.text = "• " + utils.fixTags(i, m, args.nohtml)
                        continue
                    #legendary = ET.SubElement(monster, 'legendary')
                    for e in utils.getEntryString(t["entries"], m,
                                                  args).split("\n"):
                        text = ET.SubElement(legendary, 'text')
                        text.text = e
            if 'mythicEncounter' in l:
                mythic = ET.SubElement(monster, 'legendary')
                name = ET.SubElement(mythic, 'name')
                name.text = "{} as a Mythic Encounter".format(m["name"])
                for e in utils.getEntryString(l["mythicEncounter"], m,
                                              args).split("\n"):
                    text = ET.SubElement(mythic, 'text')
                    text.text = e

    if 'spellcasting' in m:
        spells = []
        for s in m['spellcasting']:
            trait = ET.SubElement(monster, 'trait')
            name = ET.SubElement(trait, 'name')
            name.text = utils.remove5eShit(s['name'])
            for e in s['headerEntries']:
                text = ET.SubElement(trait, 'text')
                text.text = utils.fixTags(e, m, args.nohtml)

            if "will" in s:
                text = ET.SubElement(trait, 'text')
                willspells = s['will']
                text.text = "At will: " + \
                    ", ".join([utils.remove5eShit(e) for e in willspells])
                for spl in willspells:
                    search = re.search(r'{@spell+ (.*?)(\|.*)?}', spl,
                                       re.IGNORECASE)
                    if search is not None:
                        spells.append(search.group(1))

            if "daily" in s:
                for timeframe, lis in s['daily'].items():
                    text = ET.SubElement(trait, 'text')
                    dailyspells = lis
                    t = "{}/day{}: ".format(
                        timeframe[0], " each" if len(timeframe) > 1 else "")
                    text.text = t + \
                        ", ".join([utils.fixTags(e,m,args.nohtml) for e in dailyspells])
                    for spl in dailyspells:
                        search = re.search(r'{@spell+ (.*?)(\|.*)?}', spl,
                                           re.IGNORECASE)
                        if search is not None:
                            spells.append(search.group(1))

            if "spells" in s:
                slots = []
                for level, obj in s['spells'].items():
                    text = ET.SubElement(trait, 'text')
                    spellbois = obj['spells']
                    t = "• {} level ({} slots): ".format(
                        utils.ordinal(int(level)), obj['slots'] if 'slots' in
                        obj else 0) if level != "0" else "Cantrips (at will): "
                    if level != "0":
                        slots.append(
                            str(obj['slots'] if 'slots' in obj else 0))
                    text.text = t + \
                        ", ".join([utils.fixTags(e,m,args.nohtml) for e in spellbois])
                    for spl in spellbois:
                        search = re.search(r'{@spell+ (.*?)(\|.*)?}', spl,
                                           re.IGNORECASE)
                        if search is not None:
                            spells.append(search.group(1))
                slotse = ET.SubElement(monster, 'slots')
                slotse.text = ", ".join(slots)
            if 'footerEntries' in s:
                for e in s['footerEntries']:
                    text = ET.SubElement(trait, 'text')
                    text.text = utils.fixTags(e, m, args.nohtml)

        spellse = ET.SubElement(monster, 'spells')
        spellse.text = ", ".join(spells)

    description = ET.SubElement(monster, 'description')
    description.text = ""
    if 'entries' in m and not args.srd:
        description.text += utils.getEntryString(m["entries"], m, args)

    if sourcetext: description.text += "\n<i>Source: {}</i>".format(sourcetext)
    if args.nohtml:
        description.text = re.sub('</?(i|b|spell)>', '', description.text)
    environment = ET.SubElement(monster, 'environment')
    if 'environment' in m:
        environment.text = ", ".join([x for x in m['environment']])
Exemple #2
0
def parseItem(m, compendium, args):
    if '_copy' in m:
        if args.verbose:
            print("COPY: " + m['name'] + " from " + m['_copy']['name'] +
                  " in " + m['_copy']['source'])
        xtrsrc = "./data/items.json"
        try:
            with open(xtrsrc) as f:
                d = json.load(f)
                f.close()
            mcpy = m
            for mn in d['item']:
                itemfound = False
                if mn['name'] == mcpy['_copy']['name']:
                    m = mn
                    m['name'] = mcpy['name']
                    m['source'] = mcpy['source']
                    if "otherSources" in mcpy:
                        m["otherSources"] = mcpy["otherSources"]
                    m['page'] = mcpy['page']
                    if '_mod' in mcpy['_copy']:
                        m = utils.modifyItem(m, mcpy['_copy']['_mod'])
                    itemfound = True
                    break
            if not itemfound:
                print("Could not find ", mcpy['_copy']['name'])
        except IOError as e:
            if args.verbose:
                print("Could not load additional source ({}): {}".format(
                    e.errno, e.strerror))
            return

    itm = ET.SubElement(compendium, 'item')
    name = ET.SubElement(itm, 'name')
    name.text = m['name']

    if args.nohtml:
        heading = ET.SubElement(itm, 'detail')
    else:
        heading = ET.SubElement(itm, 'heading')
    headings = []

    typ = ET.SubElement(itm, 'type')
    if 'type' in m:
        typ.text = m['type']
        if m['type'] == "AIR":
            typ.text = 'G'
        if m['type'] == "AT":
            typ.text = 'G'
        if m['type'] == "FD":
            typ.text = 'G'
        if m['type'] == "GS":
            typ.text = 'G'
        if m['type'] == "INS":
            typ.text = 'G'
        if m['type'] == "MNT":
            typ.text = 'G'
        if m['type'] == "MR":
            typ.text = 'W'
        if m['type'] == "OTH":
            typ.text = 'G'
        if m['type'] == "SCF":
            if 'rod' in m['name'].lower():
                typ.text = 'RD'
            elif 'wand' in m['name'].lower():
                typ.text = 'WD'
            elif 'staff' in m['name'].lower():
                typ.text = 'ST'
            typ.text = 'G'
        if m['type'] == "SHP":
            typ.text = 'G'
        if m['type'] == "T":
            typ.text = 'G'
        if m['type'] == "TAH":
            typ.text = 'G'
        if m['type'] == "TG":
            typ.text = 'G'
        if m['type'] == "VEH":
            typ.text = 'G'
        if m['type'] == 'GV':
            typ.text = 'G'
            headings.append("Generic Variant")

    if 'wondrous' in m and m['wondrous']:
        magic = ET.SubElement(itm, 'magic')
        magic.text = "1"
        headings.append("Wondrous item (tattoo)"
                        if 'tattoo' in m and m['tattoo'] else "Wondrous item")
        if 'type' not in m:
            typ.text = 'W'

    if 'tier' in m: headings.append(m['tier'])

    if 'curse' in m and m['curse']: headings.append("Cursed item")

    weight = ET.SubElement(itm, 'weight')
    if 'weight' in m: weight.text = str(m['weight'])

    if 'rarity' in m and m['rarity'] != 'None' and m[
            'rarity'] != 'Unknown' and not args.nohtml:
        rarity = ET.SubElement(itm, 'rarity')
        rarity.text = str(m['rarity']).title()
        if m['rarity'] != 'None' and m['rarity'] != 'Unknown':
            headings.append(str(m['rarity']).title())

    if 'value' in m:
        value = ET.SubElement(itm, 'value')
        if args.nohtml:
            value.text = str(m['value'] / 100)
        elif m['value'] >= 100:
            value.text = "{:g} gp".format(m['value'] / 100)
        elif m['value'] >= 10:
            value.text = "{:g} sp".format(m['value'] / 10)
        else:
            value.text = "{:g} cp".format(m['value'])

    if 'staff' in m and m['staff']:
        headings.append('Staff')
        if 'type' not in m or m['type'] == 'SCF':
            typ.text = 'ST'

    if 'wand' in m and m['wand']:
        headings.append('Wand')
        if 'type' not in m or m['type'] == 'SCF':
            typ.text = 'WD'

    if 'weapon' in m and m['weapon'] and 'weaponCategory' in m:
        headings.append(m['weaponCategory'] + " Weapon")
        if m['weaponCategory'] == 'martial':
            if 'property' in m:
                m['property'].append('M')
            else:
                m['property'] = ['M']

    prop = ET.SubElement(itm, 'property')
    if 'property' in m:
        if 'AF' in m['property']:
            headings.append("Ammunication (futuristic)")
            m['property'] = list(filter(lambda x: (x != 'AF'), m['property']))
            if 'A' not in m['property']:
                m['property'].append('A')
        if 'RLD' in m['property']:
            headings.append("Reload")
            m['property'] = list(filter(lambda x: (x != 'RLD'), m['property']))
            if 'LD' not in m['property']: m['property'].append('LD')
        if 'BF' in m['property']:
            headings.append("Burst Fire")
            m['property'] = list(filter(lambda x: (x != 'BF'), m['property']))
            if 'R' not in m['property']: m['property'].append('R')
        prop.text = ",".join(m['property'])

    if 'type' in m:
        if m['type'] == 'LA':
            headings.append("Light Armor")
        elif m['type'] == 'MA':
            headings.append("Medium Armor")
        elif m['type'] == 'HA':
            headings.append("Heavy Armor")
        elif m['type'] == 'S':
            headings.append("Shield")
        elif m['type'] == 'SCF':
            headings.append("Spellcasting Focus")
        elif m['type'] == 'R':
            headings.append('Ranged Weapon')
        elif m['type'] == 'M':
            headings.append('Melee Weapon')
        elif m['type'] == 'A':
            headings.append('Ammunition')
        elif m['type'] == 'G':
            headings.append('Adventuring Gear')
        elif m['type'] == 'T':
            headings.append('Tools')
        elif m['type'] == 'AT':
            headings.append('Artisan Tools')
        elif m['type'] == 'GS':
            headings.append('Gaming Set')
        elif m['type'] == 'TG':
            headings.append('Trade Good')
        elif m['type'] == 'INS':
            headings.append('Instrument')
        elif m['type'] == 'MNT':
            headings.append('Mount')
        elif m['type'] == 'VEH':
            headings.append('Vehicle (land)')
        elif m['type'] == 'AIR':
            headings.append('Vehicle (air)')
        elif m['type'] == 'SHP':
            headings.append('Vehicle (water)')
        elif m['type'] == 'TAH':
            headings.append('Tack and Harness')
        elif m['type'] == 'FD':
            headings.append('Food and Drink')
        elif m['type'] == 'MR':
            headings.append('Magic Rune')
        elif m['type'] == 'OTH':
            headings.append('Other')
    if not args.nohtml:
        attunement = ET.SubElement(itm, 'attunement')
        if 'reqAttune' in m:
            if m['reqAttune'] == True:
                attunement.text = "Requires Attunement"
            else:
                attunement.text = "Requires Attunement " + m['reqAttune']
            headings.append("({})".format(attunement.text))

    if 'dmg1' in m:
        dmg1 = ET.SubElement(itm, 'dmg1')
        dmg1.text = utils.remove5eShit(m['dmg1'])

    if 'dmg2' in m:
        dmg2 = ET.SubElement(itm, 'dmg2')
        dmg2.text = utils.remove5eShit(m['dmg2'])

    if 'dmgType' in m:
        dmgType = ET.SubElement(itm, 'dmgType')
        if m['dmgType'] == 'O':
            dmgType.text = 'FC'
        elif m['dmgType'] == 'I':
            dmgType.text = 'PS'
        else:
            dmgType.text = m['dmgType']

    if 'range' in m:
        rng = ET.SubElement(itm, 'range')
        rng.text = m['range']

    if 'ac' in m:
        ac = ET.SubElement(itm, 'ac')
        ac.text = str(m['ac'])

    if 'bonus' in m:
        if 'type' in m and m['type'] in ['LA', 'MA', 'HA', 'S']:
            bonus = ET.SubElement(itm, 'modifier', {"category": "bonus"})
            bonus.text = "ac {}".format(m['bonus'])
        elif 'type' in m and m['type'] in ['M', 'R', 'A']:
            bonus = ET.SubElement(itm, 'modifier', {"category": "bonus"})
            bonus.text = "weapon attack {}".format(m['bonus'])
            bonus = ET.SubElement(itm, 'modifier', {"category": "bonus"})
            bonus.text = "weapon damage {}".format(m['bonus'])
        elif 'staff' in m and m['staff']:
            bonus = ET.SubElement(itm, 'modifier', {"category": "bonus"})
            bonus.text = "weapon attack {}".format(m['bonus'])
            bonus = ET.SubElement(itm, 'modifier', {"category": "bonus"})
            bonus.text = "weapon damage {}".format(m['bonus'])
        else:
            print(m)

    if 'poison' in m and m['poison']:
        headings.append('Poison')
        if 'type' not in m:
            typ.text = 'G'

    if 'entries' not in m:
        m['entries'] = []
        if 'tattoo' in m and m['tattoo']:
            m['entries'].append(
                "Produced by a special needle, this magic tattoo features designs that emphasize one color{}."
                .format(" ({})".format(m['color']) if 'color' in m else ''))
            m['entries'].append({
                "type":
                "entries",
                "name":
                "Tattoo Attunement",
                "entries": [
                    "To attune to this item, you hold the needle to your skin where you want the tattoo to appear, pressing the needle there throughout the attunement process. When the attunement is complete, the needle turns into the ink that becomes the tattoo, which appears on the skin.",
                    "If your attunement to the tattoo ends, the tattoo vanishes, and the needle reappears in your space."
                ]
            })
    if 'resist' in m:
        if 'type' in m:
            if m['type'] == "LA" or m['type'] == "MA" or m['type'] == "HA":
                m['entries'].append(
                    "You have resistance to {} damage while you wear this armor."
                    .format(m['resist']))
            elif m['type'] == "RG":
                m['entries'].append(
                    "You have resistance to {} damage while wearing this ring."
                    .format(m['resist']))
            elif m['type'] == "P":
                m['entries'].append(
                    "When you drink this potion, you gain resistance to {} damage for 1 hour."
                    .format(m['resist']))
        elif 'tattoo' in m and m['tattoo']:
            m['entries'].append({
                "type":
                "entries",
                "name":
                "Damage Resistance",
                "entries": [
                    "While the tattoo is on your skin, you have resistance to {} damage"
                    .format(m['resist'])
                ]
            })
            m['entries'].append({
                "type":
                "entries",
                "name":
                "Damage Absorption",
                "entries": [
                    "When you take {} damage, you can use your reaction to gain immunity against that instance of the damage, and you regain a number of hit points equal to half the damage you would have taken. Once this reaction is used, it can't be used again until the next dawn."
                    .format(m['resist'])
                ]
            })

    if 'stealth' in m and m['stealth']:
        stealth = ET.SubElement(itm, 'stealth')
        stealth.text = "1"
        m['entries'].append(
            "The wearer has disadvantage on Stealth (Dexterity) checks.")

    if 'strength' in m:
        strength = ET.SubElement(itm, 'strength')
        strength.text = str(m['strength'] or '')
        if m['type'] == "HA":
            m['entries'].append(
                "If the wearer has a Strength score lower than {}, their speed is reduced by 10 feet."
                .format(m['strength']))

    heading.text = ", ".join(headings)

    #    if args.nohtml:
    #        try:
    #            itm.remove(heading)
    #        except:
    #            pass

    if 'items' in m:
        if 'scfType' in m:
            if m['scfType'] == "arcane":
                m['entries'].insert(
                    0,
                    "An arcane focus is a special item–an orb, a crystal, a rod, a specially constructed staff, a wand-like length of wood, or some similar item–designed to channel the power of arcane spells. A sorcerer, warlock, or wizard can use such an item as a spellcasting focus."
                )
            elif m['scfType'] == "druid":
                m['entries'].insert(
                    0,
                    "A druidic focus might be a sprig of mistletoe or holly, a wand or scepter made of yew or another special wood, a staff drawn whole out of a living tree, or a totem object incorporating feathers, fur, bones, and teeth from sacred animals. A druid can use such an object as a spellcasting focus."
                )
            elif m['scfType'] == "holy":
                m['entries'].insert(
                    0,
                    "A holy symbol is a representation of a god or pantheon. It might be an amulet depicting a symbol representing a deity, the same symbol carefully engraved or inlaid as an emblem on a shield, or a tiny box holding a fragment of a sacred relic. A cleric or paladin can use a holy symbol as a spellcasting focus. To use the symbol in this way, the caster must hold it in hand, wear it visibly, or bear it on a shield."
                )
        for i in m['items']:
            if args.nohtml:
                m['entries'].append(re.sub(r'^(.*?)(\|.*?)?$', r'\1', i))
            else:
                m['entries'].append(
                    re.sub(r'^(.*?)(\|.*?)?$', r'<item>\1</item>', i))
    elif 'scfType' in m:
        if m['scfType'] == "arcane":
            m['entries'].insert(
                0,
                "An arcane focus is a special item designed to channel the power of arcane spells. A sorcerer, warlock, or wizard can use such an item as a spellcasting focus."
            )
        elif m['scfType'] == "druid":
            m['entries'].insert(
                0, "A druid can use this object as a spellcasting focus.")
        elif m['scfType'] == "holy":
            m['entries'].insert(
                0, "A holy symbol is a representation of a god or pantheon.")
            m['entries'].insert(
                1,
                "A cleric or paladin can use a holy symbol as a spellcasting focus. To use the symbol in this way, the caster must hold it in hand, wear it visibly, or bear it on a shield."
            )

    if 'lootTables' in m and not args.srd:
        if args.nohtml:
            m['entries'].append("Found On: {}".format(", ".join(
                m['lootTables'])))
        else:
            m['entries'].append("<i>Found On: {}</i> ".format(", ".join(
                m['lootTables'])))

    if 'source' in m and not args.srd:
        slug = slugify(m["name"])
        if args.addimgs and os.path.isdir("img") and not os.path.isfile(
                os.path.join(args.tempdir, "items",
                             slug + ".png")) and not os.path.isfile(
                                 os.path.join(args.tempdir, "items",
                                              slug + ".jpg")):
            if not os.path.isdir(os.path.join(args.tempdir, "items")):
                os.mkdir(os.path.join(args.tempdir, "items"))
            if 'image' in m:
                artworkpath = m['image']
            else:
                artworkpath = None
            itemname = m["original_name"] if "original_name" in m else m["name"]
            if artworkpath and os.path.isfile("./img/" + artworkpath):
                artworkpath = "./img/" + artworkpath
            elif os.path.isfile("./img/items/" + m["source"] + "/" + itemname +
                                ".jpg"):
                artworkpath = "./img/items/" + m[
                    "source"] + "/" + itemname + ".jpg"
            elif os.path.isfile("./img/items/" + m["source"] + "/" + itemname +
                                ".png"):
                artworkpath = "./img/items/" + m[
                    "source"] + "/" + itemname + ".png"
            elif os.path.isfile("./img/" + m["source"] + "/" + itemname +
                                ".png"):
                artworkpath = "./img/" + m["source"] + "/" + itemname + ".png"
            elif os.path.isfile("./img/" + m["source"] + "/" + itemname +
                                ".jpg"):
                artworkpath = "./img/" + m["source"] + "/" + itemname + ".jpg"
            elif os.path.isfile("./img/items/" + "/" + itemname + ".jpg"):
                artworkpath = "./img/items/" + "/" + itemname + ".jpg"
            elif os.path.isfile("./img/items/" + "/" + itemname + ".png"):
                artworkpath = "./img/items/" + "/" + itemname + ".png"
            elif os.path.isfile("./img/" + "/" + itemname + ".png"):
                artworkpath = "./img/" + "/" + itemname + ".png"
            elif os.path.isfile("./img/" + "/" + itemname + ".jpg"):
                artworkpath = "./img/" + "/" + itemname + ".jpg"
            if artworkpath is not None:
                ext = os.path.splitext(artworkpath)[1]
                copyfile(artworkpath,
                         os.path.join(args.tempdir, "items", slug + ext))
                imagetag = ET.SubElement(itm, 'image')
                imagetag.text = slug + ext
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "items", slug + ".png")):
            imagetag = ET.SubElement(itm, 'image')
            imagetag.text = slug + ".png"
        elif args.addimgs and os.path.isfile(
                os.path.join(args.tempdir, "items", slug + ".jpg")):
            imagetag = ET.SubElement(itm, 'image')
            imagetag.text = slug + ".jpg"

        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source'], args), m['page']
        ) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(
            m['source'], args)

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"], args),
                    s["page"]) if 'page' in s and s[
                        "page"] != 0 else utils.getFriendlySource(
                            s["source"], args)
        if 'entries' in m:
            if args.nohtml:
                m['entries'].append("Source: {}".format(sourcetext))
            else:
                m['entries'].append("<i>Source: {}</i>".format(sourcetext))
        else:
            if args.nohtml:
                m['entries'] = ["Source: {}".format(sourcetext)]
            else:
                m['entries'] = ["<i>Source: {}</i>".format(sourcetext)]
        if not args.nohtml:
            source = ET.SubElement(itm, 'source')
            source.text = sourcetext
    bodyText = ET.SubElement(itm, 'text')
    bodyText.text = ""

    if 'entries' in m:
        for e in m['entries']:
            if type(e) == dict and e['type'] == 'table':
                if 'caption' in e:
                    bodyText.text += "{}\n".format(e['caption'])
                if 'colLabels' in e:
                    bodyText.text += " | ".join(
                        [utils.remove5eShit(x) for x in e['colLabels']]) + "\n"
                for row in e['rows']:
                    rowthing = []
                    for r in row:
                        if isinstance(r, dict) and 'roll' in r:
                            rowthing.append(
                                "{}-{}".format(r['roll']['min'], r['roll']
                                               ['max']) if 'min' in
                                r['roll'] else str(r['roll']['exact']))
                        else:
                            rowthing.append(
                                utils.fixTags(str(r), m, args.nohtml))
                    bodyText.text += " | ".join(rowthing) + "\n"
            elif "entries" in e:
                subentries = []
                if 'name' in e:
                    if args.nohtml:
                        bodyText.text += "{}: ".format(e['name'])
                    else:
                        bodyText.text += "<b>{}:</b> ".format(e['name'])
                for sube in e["entries"]:
                    if type(sube) == str:
                        subentries.append(utils.fixTags(sube, m, args.nohtml))
                    elif type(sube) == dict and "text" in sube:
                        subentries.append(
                            utils.fixTags(sube["text"], m, args.nohtml))
                    elif type(sube) == dict and sube['type'] == 'table':
                        if 'caption' in sube:
                            subentries.append("{}".format(sube['caption']))
                        if 'colLabels' in sube:
                            subentries.append(" | ".join([
                                utils.remove5eShit(x)
                                for x in sube['colLabels']
                            ]))
                        for row in sube['rows']:
                            rowthing = []
                            for r in row:
                                if isinstance(r, dict) and 'roll' in r:
                                    rowthing.append("{}-{}".format(
                                        r['roll']['min'], r['roll']['max']
                                    ) if 'min' in r['roll'] else str(
                                        r['roll']['exact']))
                                else:
                                    rowthing.append(
                                        utils.fixTags(str(r), m, args.nohtml))
                            subentries.append(" | ".join(rowthing))
                    elif type(sube) == dict and sube[
                            "type"] == "list" and "style" in sube and sube[
                                "style"] == "list-hang-notitle":
                        for item in sube["items"]:
                            if type(item) == dict and 'type' in item and item[
                                    'type'] == 'item':
                                if args.nohtml:
                                    subentries.append("• {}: {}".format(
                                        item["name"],
                                        utils.fixTags(item["entry"], m,
                                                      args.nohtml)))
                                else:
                                    subentries.append("• <i>{}:</i> {}".format(
                                        item["name"],
                                        utils.fixTags(item["entry"], m,
                                                      args.nohtml)))
                            else:
                                subentries.append("• {}".format(
                                    utils.fixTags(item, m, args.nohtml)))
                    elif type(sube) == dict and sube["type"] == "list":
                        for item in sube["items"]:
                            if type(item) == dict and "entries" in item:
                                ssubentries = []
                                for sse in item["entries"]:
                                    if type(sse) == str:
                                        ssubentries.append(
                                            utils.fixTags(sse, m, args.nohtml))
                                    elif type(sse) == dict and "text" in sse:
                                        ssubentries.append(
                                            utils.fixTags(
                                                sse["text"], m, args.nohtml))
                                    subentries.append("\n".join(ssubentries))
                            elif type(
                                    item) == dict and 'type' in item and item[
                                        'type'] == 'item':
                                if args.nohtml:
                                    subentries.append("• {}: {}".format(
                                        item["name"],
                                        utils.fixTags(item["entry"], m,
                                                      args.nohtml)))
                                else:
                                    subentries.append("• <i>{}:</i> {}".format(
                                        item["name"],
                                        utils.fixTags(item["entry"], m,
                                                      args.nohtml)))
                            elif type(item) == dict and item[
                                    "type"] == "list" and "style" in item and item[
                                        "style"] == "list-hang-notitle":
                                for subitem in item["items"]:
                                    if args.nohtml:
                                        subentries.append("• {}: {}".format(
                                            subitem["name"],
                                            utils.fixTags(
                                                subitem["entry"], m,
                                                args.nohtml)) + "\n")
                                    else:
                                        subentries.append(
                                            "• <i>{}:</i> {}".format(
                                                subitem["name"],
                                                utils.fixTags(
                                                    subitem["entry"], m,
                                                    args.nohtml)) + "\n")
                            else:
                                subentries.append("• {}".format(
                                    utils.fixTags(item, m, args.nohtml)))
                bodyText.text += "\n".join(subentries) + "\n"
            else:
                if type(e) == dict and e[
                        "type"] == "list" and "style" in e and e[
                            "style"] == "list-hang-notitle":
                    for item in e["items"]:
                        if type(item) == dict:
                            if args.nohtml:
                                bodyText.text += "• {}: {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)) + "\n"
                            else:
                                bodyText.text += "• <i>{}:</i> {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)) + "\n"
                        else:
                            bodyText.text += "• {}".format(
                                utils.fixTags(item, m, args.nohtml)) + "\n"
                elif type(e) == dict and e["type"] == "list":
                    for item in e["items"]:
                        if "entries" in item:
                            subentries = []
                            for sube in item["entries"]:
                                if type(sube) == str:
                                    subentries.append(
                                        utils.fixTags(sube, m, args.nohtml))
                                elif type(sube) == dict and "text" in sube:
                                    subentries.append(
                                        utils.fixTags(sube["text"], m,
                                                      args.nohtml))
                                bodyText.text += "\n".join(subentries) + "\n"
                        else:
                            bodyText.text += "• {}".format(
                                utils.fixTags(item, m, args.nohtml)) + "\n"
                else:
                    bodyText.text += utils.fixTags(e, m, args.nohtml) + "\n"

    bodyText.text = bodyText.text.rstrip()
    for match in re.finditer(r'([0-9])+[dD]([0-9])+([ ]?[-+][ ]?[0-9]+)?',
                             bodyText.text):
        if not itm.find("./[roll='{}']".format(match.group(0))):
            roll = ET.SubElement(itm, 'roll')
            roll.text = "{}".format(match.group(0)).replace(' ', '')
Exemple #3
0
def parseBackground(m, compendium, args):
    if '_copy' in m:
        if args.verbose:
            print("COPY: " + m['name'] + " from " + m['_copy']['name'] +
                  " in " + m['_copy']['source'])
        xtrsrc = "./data/backgrounds.json"
        try:
            with open(xtrsrc) as f:
                d = json.load(f)
                f.close()
            mcpy = m
            for mn in d['background']:
                backgroundfound = False
                if mn['name'] == mcpy['_copy']['name']:
                    m = mn
                    m['name'] = mcpy['name']
                    m['source'] = mcpy['source']
                    if "otherSources" in mcpy:
                        m["otherSources"] = mcpy["otherSources"]
                    m['page'] = mcpy['page']
                    if '_mod' in mcpy['_copy']:
                        m = utils.modifyItem(m, mcpy['_copy']['_mod'])
                    backgroundfound = True
                    break
            if not backgroundfound:
                print("Could not find ", mcpy['_copy']['name'])
        except IOError as e:
            if args.verbose:
                print("Could not load additional source ({}): {}".format(
                    e.errno, e.strerror))
            return

    bg = ET.SubElement(compendium, 'background')
    name = ET.SubElement(bg, 'name')
    match = re.match(r'Variant (.*?) \((.*?)\)', m['name'])
    if match:
        name.text = "{} / {}".format(match.group(1), match.group(2))
    else:
        name.text = m['name']

    if 'entries' not in m:
        m['entries'] = []

    if 'source' in m:
        name = m["name"]
        if args.addimgs and os.path.isdir(
                "./img") and not os.path.isfile("./items/" + name + ".png"):
            if not os.path.isdir("./items/"):
                os.mkdir("./items/")
            artworkpath = None
            if os.path.isfile("./img/items/" + m["name"] + ".jpg"):
                artworkpath = "./img/items/" + m["name"] + ".jpg"
            elif os.path.isfile("./img/items/" + m["name"] + ".png"):
                artworkpath = "./img/items/" + m["name"] + ".png"
            elif os.path.isfile("./img/items/" + m["source"] + "/" +
                                m["name"] + ".png"):
                artworkpath = "./img/items/" + m["source"] + "/" + m[
                    "name"] + ".png"
            if artworkpath is not None:
                if args.verbose:
                    print("Converting Image: " + artworkpath)
                with Image(filename=artworkpath) as img:
                    img.format = 'png'
                    img.save(filename="./items/" + name + ".png")
                    imagetag = ET.SubElement(bg, 'image')
                    imagetag.text = name + ".png"
        elif args.addimgs and os.path.isfile("./items/" + name + ".png"):
            imagetag = ET.SubElement(bg, 'image')
            imagetag.text = name + ".png"

        #source = ET.SubElement(bg, 'source')
        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source']), m['page']
        ) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(
            m['source'])

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"]),
                    s["page"]) if 'page' in s and s[
                        "page"] != 0 else utils.getFriendlySource(s["source"])
        if 'entries' in m:
            if args.nohtml:
                m['entries'].append("Source: {}".format(sourcetext))
            else:
                m['entries'].append("<i>Source: {}</i>".format(sourcetext))
        else:
            if args.nohtml:
                m['entries'] = ["Source: {}".format(sourcetext)]
            else:
                m['entries'] = ["<i>Source: {}</i>".format(sourcetext)]

    prof = ET.SubElement(bg, 'proficiency')
    if 'skillProficiencies' in m:
        profs = []
        for skill in m['skillProficiencies']:
            for k, v in skill.items():
                if k != 'choose':
                    if v:
                        profs.append(k.title())
        prof.text = ", ".join(profs)

    trait = ET.SubElement(bg, 'trait')
    name = ET.SubElement(trait, 'name')
    name.text = "Description"
    description = ET.SubElement(trait, 'text')
    description.text = ""

    if 'entries' in m:
        for e in m['entries']:
            if type(e) == dict:
                if 'name' in e:
                    trait = ET.SubElement(bg, 'trait')
                    name = ET.SubElement(trait, 'name')
                    name.text = e['name']
                    text = ET.SubElement(trait, 'text')
                    text.text = ""
                else:
                    text = description
                if "colLabels" in e:
                    text.text += " | ".join(
                        [utils.remove5eShit(x) for x in e['colLabels']])
                    text.text += "\n"
                    for row in e['rows']:
                        rowthing = []
                        for r in row:
                            if isinstance(r, dict) and 'roll' in r:
                                rowthing.append(
                                    "{}-{}".format(r['roll']['min'], r['roll']
                                                   ['max']) if 'min' in
                                    r['roll'] else str(r['roll']['exact']))
                            else:
                                rowthing.append(
                                    utils.fixTags(str(r), m, args.nohtml))
                        text.text += " | ".join(rowthing) + "\n"
                elif "entries" in e:
                    subentries = []
                    for sube in e["entries"]:
                        if type(sube) == str:
                            subentries.append(
                                utils.fixTags(sube, m, args.nohtml))
                        elif type(sube) == dict and "text" in sube:
                            subentries.append(
                                utils.fixTags(sube["text"], m, args.nohtml))
                        elif type(sube) == dict and sube[
                                "type"] == "list" and "style" in sube and sube[
                                    "style"] == "list-hang-notitle":
                            for item in sube["items"]:
                                if type(item
                                        ) == dict and 'type' in item and item[
                                            'type'] == 'item':
                                    if args.nohtml:
                                        subentries.append("• {}: {}".format(
                                            item["name"],
                                            utils.fixTags(
                                                item["entry"], m,
                                                args.nohtml)))
                                    else:
                                        subentries.append(
                                            "• <i>{}:</i> {}".format(
                                                item["name"],
                                                utils.fixTags(
                                                    item["entry"], m,
                                                    args.nohtml)))
                                else:
                                    subentries.append("• {}".format(
                                        utils.fixTags(item, m, args.nohtml)))
                        elif type(sube) == dict and sube["type"] == "list":
                            for item in sube["items"]:
                                if type(item) == dict and "entries" in item:
                                    ssubentries = []
                                    for sse in item["entries"]:
                                        if type(sse) == str:
                                            ssubentries.append(
                                                utils.fixTags(
                                                    sse, m, args.nohtml))
                                        elif type(
                                                sse) == dict and "text" in sse:
                                            ssubentries.append(
                                                utils.fixTags(
                                                    sse["text"], m,
                                                    args.nohtml))
                                        subentries.append(
                                            "\n".join(ssubentries))
                                elif type(
                                        item
                                ) == dict and 'type' in item and item[
                                        'type'] == 'item':
                                    if args.nohtml:
                                        subentries.append("• {}: {}".format(
                                            item["name"],
                                            utils.fixTags(
                                                item["entry"], m,
                                                args.nohtml)))
                                    else:
                                        subentries.append(
                                            "• <i>{}:</i> {}".format(
                                                item["name"],
                                                utils.fixTags(
                                                    item["entry"], m,
                                                    args.nohtml)))
                                else:
                                    subentries.append("• {}".format(
                                        utils.fixTags(item, m, args.nohtml)))
                        else:
                            if "colLabels" in sube:
                                tabletext = ""
                                tabletext += " | ".join([
                                    utils.remove5eShit(x)
                                    for x in sube['colLabels']
                                ])
                                tabletext += "\n"
                                for row in sube['rows']:
                                    rowthing = []
                                    for r in row:
                                        if isinstance(r, dict) and 'roll' in r:
                                            rowthing.append("{}-{}".format(
                                                r['roll']['min'], r['roll']
                                                ['max']
                                            ) if 'min' in r['roll'] else str(
                                                r['roll']['exact']))
                                        else:
                                            rowthing.append(
                                                utils.fixTags(
                                                    str(r), m, args.nohtml))
                                    tabletext += " | ".join(rowthing) + "\n"
                                subentries.append(tabletext)

                    text.text += "\n".join(subentries) + "\n"
                else:
                    if type(e) == dict and e[
                            "type"] == "list" and "style" in e and e[
                                "style"] == "list-hang-notitle":
                        for item in e["items"]:
                            if 'entries' in item and 'entry' not in item:
                                item['entry'] = ", ".join(item['entries'])
                            if args.nohtml:
                                text.text += "• {}: {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)) + "\n"
                            else:
                                text.text += "• <i>{}:</i> {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)) + "\n"
                    elif type(e) == dict and e["type"] == "list":
                        for item in e["items"]:
                            if "entries" in item:
                                subentries = []
                                for sube in item["entries"]:
                                    if type(sube) == str:
                                        subentries.append(
                                            utils.fixTags(
                                                sube, m, args.nohtml))
                                    elif type(sube) == dict and "text" in sube:
                                        subentries.append(
                                            utils.fixTags(
                                                sube["text"], m, args.nohtml))
                                    text.text += "\n".join(subentries) + "\n"
                            else:
                                text.text += "• {}".format(
                                    utils.fixTags(item, m, args.nohtml)) + "\n"
            else:
                description.text += utils.fixTags(e, m, args.nohtml) + "\n"

    description.text = description.text.rstrip()
Exemple #4
0
def parseFeat(m, compendium, args):
    feat = ET.SubElement(compendium, 'feat')
    name = ET.SubElement(feat, 'name')
    name.text = m['name']

    prereqs = ET.SubElement(feat,'prerequisite')
    if 'prerequisite' in m:
        prereq = []
        for pre in m['prerequisite']:
            if 'ability' in pre:
                if type(pre['ability']) == list:
                    abilityor = []
                    if all(next(iter(v.values())) == next(iter(pre['ability'][0].values())) for v in pre['ability']):
                        for v in pre['ability']:
                            for s,val in v.items():
                                abilityor.append(stats[s])
                        prereq.append("{} {} or higher".format(" or ".join(abilityor),next(iter(pre['ability'][0].values()))))
                    else:
                        for v in pre['ability']:
                            for s,val in v.items():
                                abilityor.append("{} {} or higher".format(stats[k],val))
                        prereq.append(" or ".join(abilityor))
                else:
                    for k,v in pre['ability'].items():
                        prereq.append("{} {} or higher".format(stats[k],v))
            if 'spellcasting' in pre and pre['spellcasting']:
                prereq.append("The ability to cast at least one spell")
            if 'proficiency' in pre:
                for prof in pre['proficiency']:
                    for k,v in prof.items():
                        prereq.append("Proficiency with {} {}".format(v,k))
            if 'race' in pre:
                for r in pre['race']:
                    prereq.append("{}{}".format(r['name']," ({})".format(r['subrace']) if 'subrace' in r else "").title())
        prereqs.text = ", ".join(prereq)

    if 'entries' not in m:
        m['entries'] = []

    if 'source' in m:
        name = m["name"]
        if args.addimgs and os.path.isdir("./img") and not os.path.isfile("./items/" + name + ".png"):
            if not os.path.isdir("./items/"):
                os.mkdir("./items/")
            artworkpath = None
            if os.path.isfile("./img/items/" + m["name"] + ".jpg"):
                artworkpath = "./img/items/" + m["name"] + ".jpg"
            elif os.path.isfile("./img/items/" + m["name"] + ".png"):
                artworkpath = "./img/items/" + m["name"] + ".png"
            elif os.path.isfile("./img/items/" + m["source"] + "/" + m["name"] + ".png"):
                artworkpath = "./img/items/" + m["source"] + "/" + m["name"] + ".png"
            if artworkpath is not None:
                if args.verbose:
                    print("Converting Image: " + artworkpath)
                with Image(filename=artworkpath) as img:
                    img.format='png'
                    img.save(filename="./items/" + name + ".png")
                    imagetag = ET.SubElement(feat, 'image')
                    imagetag.text = name + ".png"
        elif args.addimgs and os.path.isfile("./items/" + name + ".png"):
            imagetag = ET.SubElement(feat, 'image')
            imagetag.text = name + ".png"

        #source = ET.SubElement(feat, 'source')
        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source']), m['page']) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(m['source'])

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"]), s["page"]) if 'page' in s and s["page"] != 0 else utils.getFriendlySource(s["source"])
        if 'entries' in m:
            if args.nohtml:
                m['entries'].append("Source: {}".format(sourcetext))
            else:
                m['entries'].append("<i>Source: {}</i>".format(sourcetext))
        else:
            if args.nohtml:
                m['entries'] = ["Source: {}".format(sourcetext)]
            else:
                m['entries'] = ["<i>Source: {}</i>".format(sourcetext)]
    bodyText = ET.SubElement(feat, 'text')
    bodyText.text = ""

    if 'ability' in m:
        for ability in m['ability']:
            for k,v in ability.items():
                if k in stats:
                    bonusmod = ET.SubElement(feat, 'modifier', {'category': 'ability score'})
                    bonusmod.text = "{} {:+d}".format(stats[k],v)
                elif k == 'choose':
                    for e in m['entries']:
                        if type(e) == dict and e['type'] == 'list':
                            if len(v["from"]) != 6:
                                e['items'].insert(0,"Increase your {} score by {}, to a maximum of 20".format(" or ".join([stats[x] for x in v["from"]]),v["amount"]))
    if 'entries' in m:
        for e in m['entries']:
            if "colLabels" in e:
                bodyText.text += " | ".join([utils.remove5eShit(x)
                                        for x in e['colLabels']])
                bodyText.text += "\n"
                for row in e['rows']:
                    rowthing = []
                    for r in row:
                        if isinstance(r, dict) and 'roll' in r:
                            rowthing.append(
                                "{}-{}".format(
                                    r['roll']['min'],
                                    r['roll']['max']) if 'min' in r['roll'] else str(
                                    r['roll']['exact']))
                        else:
                            rowthing.append(utils.fixTags(str(r),m,args.nohtml))
                    bodyText.text += " | ".join(rowthing) + "\n"
            elif "entries" in e:
                subentries = []
                if 'name' in e:
                    if args.nohtml:
                        bodyText.text += "{}: ".format(e['name'])
                    else:
                        bodyText.text += "<b>{}:</b> ".format(e['name'])
                for sube in e["entries"]:
                    if type(sube) == str:
                        subentries.append(utils.fixTags(sube,m,args.nohtml))
                    elif type(sube) == dict and "text" in sube:
                        subentries.append(utils.fixTags(sube["text"],m,args.nohtml))
                    elif type(sube) == dict and sube["type"] == "list" and "style" in sube and sube["style"] == "list-hang-notitle":
                        for item in sube["items"]:
                            if type(item) == dict and 'type' in item and item['type'] == 'item':
                                if args.nohtml:
                                    subentries.append("• {}: {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                                else:
                                    subentries.append("• <i>{}:</i> {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                            else:
                                subentries.append("• {}".format(utils.fixTags(item,m,args.nohtml)))
                    elif type(sube) == dict and sube["type"] == "list":
                        for item in sube["items"]:
                            if type(item) == dict and "entries" in item:
                                ssubentries = []                    
                                for sse in item["entries"]:
                                    if type(sse) == str:
                                        ssubentries.append(utils.fixTags(sse,m,args.nohtml))
                                    elif type(sse) == dict and "text" in sse:
                                        ssubentries.append(utils.fixTags(sse["text"],m,args.nohtml))
                                    subentries.append("\n".join(ssubentries))
                            elif type(item) == dict and 'type' in item and item['type'] == 'item':
                                if args.nohtml:
                                    subentries.append("• {}: {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                                else:
                                    subentries.append("• <i>{}:</i> {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                            else:
                                subentries.append("• {}".format(utils.fixTags(item,m,args.nohtml)))
                bodyText.text += "\n".join(subentries) + "\n"
            else:
                if type(e) == dict and e["type"] == "list" and "style" in e and e["style"] == "list-hang-notitle":
                    for item in e["items"]:
                        if args.nohtml:
                            bodyText.text += "• {}: {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)) + "\n"
                        else:
                            bodyText.text += "• <i>{}:</i> {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)) + "\n"
                elif type(e) == dict and e["type"] == "list":
                    for item in e["items"]:
                        if "entries" in item:
                            subentries = []                    
                            for sube in item["entries"]:
                                if type(sube) == str:
                                    subentries.append(utils.fixTags(sube,m,args.nohtml))
                                elif type(sube) == dict and "text" in sube:
                                    subentries.append(utils.fixTags(sube["text"],m,args.nohtml))
                                bodyText.text += "\n".join(subentries) + "\n"
                        else:
                            bodyText.text += "• {}".format(utils.fixTags(item,m,args.nohtml)) + "\n"
                else:
                    bodyText.text += utils.fixTags(e,m,args.nohtml) + "\n"

    bodyText.text = bodyText.text.rstrip()
    for match in re.finditer(r'You gain proficiency in the ([^ ]*?)( and (.*?))? skill',bodyText.text):
        bonusmod = ET.SubElement(feat, 'proficiency')
        bonusmod.text = match.group(1)
        if match.group(2) and match.group(3):
            bonusmod.text = ", " + match.group(3)
Exemple #5
0
def parseClass(m, compendium, args):
    #    for eachClasss in compendium.findall('Class'):
    #        if eachClasss.find('name').text == m['name']:
    #            m['name'] = "{} (DUPLICATE IN {})".format(m['name'],m['source'])
    stats = {
        "str": "Strength",
        "dex": "Dexterity",
        "con": "Constitution",
        "int": "Intelligence",
        "wis": "Wisdom",
        "cha": "Charisma"
    }
    slots = ""
    numberofSkills = ""
    if m['source'] == "UASidekicks":
        m['hd'] = {"number": 1, "faces": 10}
        m["startingProficiencies"] = {'skills': []}

    Class = ET.SubElement(compendium, 'class')
    name = ET.SubElement(Class, 'name')
    name.text = m['name']
    hd = ET.SubElement(Class, 'hd')
    hd.text = str(m['hd']['faces'])
    saveProficiency = []
    for stat, value in stats.items():
        if 'proficiency' in m and stat in m['proficiency']:
            saveProficiency.append("{}".format(stats[stat]))
    proficiency = ET.SubElement(Class, 'proficiency')
    proficiencyList = []
    numSkills = ET.SubElement(Class, 'numSkills')

    for skill in m['startingProficiencies']['skills']:
        if 'choose' in skill and 'from' in skill['choose']:
            skillList = skill['choose']['from']
            proficiencyList = saveProficiency + skillList
            proficiencytext = ", ".join(proficiencyList).title()
            proficiency.text = proficiencytext
            numberofSkills = str(skill['choose']['count'])
            numSkills.text = str(skill['choose']['count'])

    spellcastingAbility = ""
    if 'spellcastingAbility' in m:
        spellAbility = ET.SubElement(Class, 'spellAbility')
        spellcastingAbility = "{}".format(stats[m['spellcastingAbility']])
        spellAbility.text = spellcastingAbility
    myattributes = {"level": "1"}
    autolevel = ET.SubElement(Class, 'autolevel', myattributes)
    featureattributes = {"optional": "YES"}
    StartingFeature = ET.SubElement(autolevel, 'feature', featureattributes)
    SFName = ET.SubElement(StartingFeature, 'name')
    SFName.text = "Starting " + m['name']
    SFText = ET.SubElement(StartingFeature, 'text')
    SFText.text = "As a 1st-level " + m[
        'name'] + ", you begin play with " + str(
            m['hd']['faces']) + "+your Constitution modifier hit points."
    SFText = ET.SubElement(StartingFeature, 'text')
    SFText.text = ""
    SFText = ET.SubElement(StartingFeature, 'text')
    SFText.text = "You are proficient with the following items, in addition to any proficiencies provided by your race or background."
    SFText = ET.SubElement(StartingFeature, 'text')
    if "armor" in m['startingProficiencies']:
        armortext = ", ".join([
            x if type(x) == str else x['full']
            for x in m['startingProficiencies']['armor']
        ])
    else:
        armortext = "none"
    SFText.text = "• Armor: " + armortext
    SFText = ET.SubElement(StartingFeature, 'text')
    if "weapons" in m['startingProficiencies']:
        weapontext = ", ".join(m['startingProficiencies']['weapons'])
    else:
        weapontext = "none"
    SFText.text = "• Weapons: " + weapontext
    SFText = ET.SubElement(StartingFeature, 'text')
    if "tools" in m['startingProficiencies']:
        SFText.text = "• Tools: " + ", ".join(
            m['startingProficiencies']['tools'])
    else:
        SFText.text = "• Tools: none"
    SFText = ET.SubElement(StartingFeature, 'text')
    if numberofSkills != "":
        SFText.text = "• Skills: Choose " + numberofSkills + " from " + ", ".join(
            skillList).title()
        SFText = ET.SubElement(StartingFeature, 'text')
        SFText.text = ""
    SFText = ET.SubElement(StartingFeature, 'text')
    if 'startingEquipment' in m:
        SFText.text = "You begin play with the following equipment, in addition to any equipment provided by your background."
        for startingEquipment in m['startingEquipment']['default']:
            SFText = ET.SubElement(StartingFeature, 'text')
            SFText.text = "• " + utils.fixTags(startingEquipment, m,
                                               args.nohtml)
        SFText = ET.SubElement(StartingFeature, 'text')
        SFText.text = ""
        if "goldAlternative" in m['startingEquipment']:
            SFText = ET.SubElement(StartingFeature, 'text')
            SFText.text = "Alternatively, you may start with " + utils.fixTags(
                m['startingEquipment']['goldAlternative'], m,
                args.nohtml) + " gp and choose your own equipment."
            SFText = ET.SubElement(StartingFeature, 'text')
            SFText.text = ""
    SFText = ET.SubElement(StartingFeature, 'text')
    SFText.text = "Source: " + utils.getFriendlySource(
        m['source']) + " p. " + str(m['page'])
    if 'multiclassing' in m:
        myattributes = {"level": "1"}
        autolevel = ET.SubElement(Class, 'autolevel', myattributes)
        featureattributes = {"optional": "YES"}
        StartingFeature = ET.SubElement(autolevel, 'feature',
                                        featureattributes)
        SFName = ET.SubElement(StartingFeature, 'name')
        SFName.text = "Multiclass " + m['name']
        SFText = ET.SubElement(StartingFeature, 'text')
        SFText.text = 'To multiclass as a ' + m[
            'name'] + ', you must meet the following prerequisites:'
        SFText = ET.SubElement(StartingFeature, 'text')
        if 'or' in m['multiclassing']['requirements']:
            MCrequirements = {}
            for requirement, value in m['multiclassing']['requirements']['or'][
                    0].items():
                MCrequirements[str(requirement)] = str(value)
                SFText = ET.SubElement(StartingFeature, 'text')
                SFText.text = "• {} {}".format(stats[requirement],
                                               MCrequirements[requirement])
        else:
            for requirement, value in m['multiclassing']['requirements'].items(
            ):
                SFText.text = "• {} {}".format(
                    stats[requirement],
                    m['multiclassing']['requirements'][requirement])
        SFText = ET.SubElement(StartingFeature, 'text')
        SFText.text = ""
        if 'proficienciesGained' in m['multiclassing'] or 'tools' in m[
                'multiclassing']:
            SFText = ET.SubElement(StartingFeature, 'text')
            SFText.text = "You gain the following proficiencies:"
            if 'proficienciesGained' in m['multiclassing']:
                SFText = ET.SubElement(StartingFeature, 'text')
                if "armor" in m['multiclassing']['proficienciesGained']:
                    MCarmortext = ", ".join([
                        x if type(x) == str else x['full'] for x in
                        m['multiclassing']['proficienciesGained']['armor']
                    ])
                else:
                    MCarmortext = "none"
                SFText.text = "• Armor: " + MCarmortext
                SFText = ET.SubElement(StartingFeature, 'text')
                if "weapons" in m['multiclassing']['proficienciesGained']:
                    MCweapontext = ", ".join(
                        m['multiclassing']['proficienciesGained']['weapons'])
                else:
                    MCweapontext = "none"
                    SFText.text = "• Weapons: " + MCweapontext
            SFText = ET.SubElement(StartingFeature, 'text')
            if "tools" in m['multiclassing']:
                MCtooltext = ", ".join(m['multiclassing']['tools'])
            else:
                MCtooltext = "none"
            SFText.text = "• Tools: " + MCtooltext
            SFText = ET.SubElement(StartingFeature, 'text')
            SFText.text = ""
        SFText = ET.SubElement(StartingFeature, 'text')
        SFText.text = "Source: " + utils.getFriendlySource(
            m['source']) + " p. " + str(m['page'])
    armor = ET.SubElement(Class, 'armor')
    armor.text = armortext
    weapons = ET.SubElement(Class, 'weapons')
    weapons.text = weapontext
    tools = ET.SubElement(Class, 'tools')
    if "tools" in m['startingProficiencies']:
        tools.text = ", ".join(m['startingProficiencies']['tools'])
    else:
        tools.text = "none"
    if 'startingEquipment' in m and "goldAlternative" in m['startingEquipment']:
        wealth = ET.SubElement(Class, 'wealth')
        wealth.text = str(
            utils.fixTags(m['startingEquipment']['goldAlternative'], m,
                          args.nohtml))
    if 'casterProgression' in m:
        FullCaster = [[3, 2, 0, 0, 0, 0, 0, 0, 0, 0],
                      [3, 3, 0, 0, 0, 0, 0, 0, 0, 0],
                      [3, 4, 2, 0, 0, 0, 0, 0, 0, 0],
                      [4, 4, 3, 0, 0, 0, 0, 0, 0, 0],
                      [4, 4, 3, 2, 0, 0, 0, 0, 0, 0],
                      [4, 4, 3, 3, 0, 0, 0, 0, 0, 0],
                      [4, 4, 3, 3, 1, 0, 0, 0, 0, 0],
                      [4, 4, 3, 3, 2, 0, 0, 0, 0, 0],
                      [4, 4, 3, 3, 3, 1, 0, 0, 0, 0],
                      [5, 4, 3, 3, 3, 2, 0, 0, 0, 0],
                      [5, 4, 3, 3, 3, 2, 1, 0, 0, 0],
                      [5, 4, 3, 3, 3, 2, 1, 0, 0, 0],
                      [5, 4, 3, 3, 3, 2, 1, 1, 0, 0],
                      [5, 4, 3, 3, 3, 2, 1, 1, 0, 0],
                      [5, 4, 3, 3, 3, 2, 1, 1, 1, 0],
                      [5, 4, 3, 3, 3, 2, 1, 1, 1, 0],
                      [5, 4, 3, 3, 3, 2, 1, 1, 1, 1],
                      [5, 4, 3, 3, 3, 3, 1, 1, 1, 1],
                      [5, 4, 3, 3, 3, 3, 2, 1, 1, 1],
                      [5, 4, 3, 3, 3, 3, 2, 2, 1, 1]]
        HalfCaster = [[0, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0,
                                           0], [0, 3, 0, 0, 0, 0],
                      [0, 3, 0, 0, 0, 0], [0, 4, 2, 0, 0,
                                           0], [0, 4, 2, 0, 0, 0],
                      [0, 4, 3, 0, 0, 0], [0, 4, 3, 0, 0,
                                           0], [0, 4, 3, 2, 0, 0],
                      [0, 4, 3, 2, 0, 0], [0, 4, 3, 3, 0,
                                           0], [0, 4, 3, 3, 0, 0],
                      [0, 4, 3, 3, 1, 0], [0, 4, 3, 3, 1,
                                           0], [0, 4, 3, 3, 2, 0],
                      [0, 4, 3, 3, 2, 0], [0, 4, 3, 3, 3,
                                           1], [0, 4, 3, 3, 3, 1],
                      [0, 4, 3, 3, 3, 2], [0, 4, 3, 3, 3, 2]]
        ThirdCaster = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 2, 0, 0, 0],
                       [0, 3, 0, 0, 0], [0, 3, 0, 0, 0], [0, 3, 0, 0, 0],
                       [0, 4, 2, 0, 0], [0, 4, 2, 0, 0], [0, 4, 2, 0, 0],
                       [0, 4, 3, 0, 0], [0, 4, 3, 0, 0], [0, 4, 3, 0, 0],
                       [0, 4, 3, 2, 0], [0, 4, 3, 2, 0], [0, 4, 3, 2, 0],
                       [0, 4, 3, 3, 0], [0, 4, 3, 3, 0], [0, 4, 3, 3, 0],
                       [0, 4, 3, 3, 1], [0, 4, 3, 3, 1]]
        #if 'Cantrips Known' in m['classTableGroups'][0]["colLabels"]:
        #    print(m['classTableGroups'][0]["colLabels"][0])
        #    print(type(m['classTableGroups'][0]["colLabels"][0]))
        #    print("Cantrips are known")
        if m['casterProgression'] == 'full':
            slots = FullCaster
        elif m['casterProgression'] == '1/2':
            slots = HalfCaster
        elif m['casterProgression'] == '1/3':
            slots = ThirdCaster
        else:
            slots = [[], [], [], [], [], [], [], [], [], [], [], [], [], [],
                     [], [], [], [], [], []]
        for table in m['classTableGroups']:
            if "title" in table and table[
                    'title'] == "Spell Slots per Spell Level":
                for lvl in range(len(table["rows"])):
                    for c in table["rows"][lvl]:
                        slots[lvl] = table["rows"][lvl]
        for table in m['classTableGroups']:
            cantripre = re.compile(
                r'{@filter ([Cc]antrips.*?)(\|.*?)?(\|.*?)?}')
            for i in range(len(table["colLabels"])):
                if cantripre.match(table["colLabels"][i]):
                    cantrips = True
                    for lvl in range(len(table["rows"])):
                        slots[lvl].insert(0, table["rows"][lvl][i])
                    break
        for levelcounter in range(len(slots)):
            while slots[levelcounter] and slots[levelcounter][-1] == 0:
                slots[levelcounter].pop()
    level = 0
    currentsubclass = 0
    currentsubclassFeature = 0

    for level in range(len(m['classFeatures'])):
        if slots:
            if slots[level]:
                attributes = {"level": str(level + 1)}
                autolevel = ET.SubElement(Class, 'autolevel', attributes)
                spellslots = ET.SubElement(autolevel, 'slots')
                currentspellevel = level
                spellslots.text = ", ".join(
                    str(e) for e in slots[currentspellevel])
        for feature in m['classFeatures'][level]:
            if 'name' in feature:
                if feature['name'] == "Ability Score Improvement":
                    attributes = {
                        "level": str(level + 1),
                        "scoreImprovement": "YES"
                    }
                else:
                    attributes = {"level": str(level + 1)}
            if args.skipua and 'source' in feature and feature[
                    'source'].startswith('UA'):
                if args.verbose:
                    print("Skipping UA Feature:", m['name'], feature['name'])
                if "gainSubclassFeature" in feature and feature[
                        "gainSubclassFeature"] == True:
                    currentsubclassFeature += 1
                continue
            if args.onlyofficial:
                if 'source' in feature and feature[
                        'source'] not in args.onlyofficial:
                    if args.verbose:
                        print("Skipping unoffical content: {} from {}".format(
                            feature['name'],
                            utils.getFriendlySource(feature['source'])))
                    if "gainSubclassFeature" in feature and feature[
                            "gainSubclassFeature"] == True:
                        currentsubclassFeature += 1
                    continue
            autolevel = ET.SubElement(Class, 'autolevel', attributes)
            attributes = {}
            ft = ET.SubElement(autolevel, 'feature', attributes)
            ftname = ET.SubElement(ft, 'name')
            ftname.text = utils.fixTags(feature["name"], m, args.nohtml)
            for subfeature in feature['entries']:
                flatten_json(subfeature, m, ft, args, level, attributes)
            if "gainSubclassFeature" in feature and feature[
                    "gainSubclassFeature"] == True:
                currentsubclass = 0
                for subclass in m['subclasses']:
                    if args.skipua and 'source' in subclass and subclass[
                            'source'].startswith('UA'):
                        if args.verbose:
                            print("Skipping UA Subclass:", m['name'],
                                  subclass['name'])
                        currentsubclass += 1
                        continue
                    if args.onlyofficial:
                        if 'source' in subclass and subclass[
                                'source'] not in args.onlyofficial:
                            if args.verbose:
                                print("Skipping unoffical content: {} from {}".
                                      format(
                                          m['name'],
                                          utils.getFriendlySource(
                                              m['source'])))
                            currentsubclass += 1
                            continue
                    attributes = {"level": str(level + 1)}
                    autolevel = ET.SubElement(Class, 'autolevel', attributes)
                    attributes = {"optional": "YES"}
                    subclassname = subclass['name']
                    ft = ET.SubElement(autolevel, 'feature', attributes)
                    #print(subclass['source'])
                    if currentsubclassFeature == 0:
                        ftname = ET.SubElement(ft, 'name')
                        ftname.text = "{}: {}".format(
                            utils.fixTags(m['subclassTitle'], m, args.nohtml),
                            subclassname)
                    for subfeature in subclass['subclassFeatures'][
                            currentsubclassFeature]:
                        if 'entries' in subfeature:
                            for entry in subfeature['entries']:
                                if type(entry) is str:
                                    fttext = ET.SubElement(ft, 'text')
                                    fttext.text = entry
                                else:
                                    if currentsubclassFeature == 0:
                                        flatten_json(entry, m, ft, args, level,
                                                     attributes)
                                    else:
                                        flatten_json(entry, m, ft, args, level,
                                                     attributes, subclassname)
                        else:
                            print("this shouldn't happen")
                        SFText = ET.SubElement(ft, 'text')
                        SFText.text = ""
                        SFText = ET.SubElement(ft, 'text')
                        if 'page' in subclass:
                            SFText.text = "Source: " + utils.getFriendlySource(
                                subclass['source']) + " p. " + str(
                                    subclass['page'])
                        else:
                            SFText.text = "Source: " + utils.getFriendlySource(
                                subclass['source'])
                    currentsubclass += 1
                currentsubclassFeature += 1
Exemple #6
0
 def flatten(x, m, args, name=''):
     if args.skipua and 'source' in m and m['source'].startswith('UA'):
         if args.verbose:
             print("Skipping UA Content: ", m['name'])
         return
     if args.onlyofficial:
         if 'source' in m and m['source'] not in args.onlyofficial:
             if args.verbose:
                 print("Skipping unoffical content: {} from {}".format(
                     m['name'], utils.getFriendlySource(m['source'])))
             return
     skip = False
     options = False
     if type(x) is str:
         subtitle = ''
         if name == "name":
             text = ET.SubElement(m, 'name')
             #print(str(x))
             #print(str(m))
             text.text = utils.fixTags(x, m, args.nohtml)
         elif name == "text":
             text = ET.SubElement(m, 'text')
             text.text = "   " + utils.fixTags(x, m, args.nohtml)
         elif name == "nametext":
             text = ET.SubElement(m, 'text')
             text.text = utils.fixTags(x, m, args.nohtml)
         elif name == "list":
             text = ET.SubElement(m, 'text')
             text.text = "• " + utils.fixTags(x, m, args.nohtml)
         else:
             text = ET.SubElement(m, 'text')
             text.text = utils.fixTags(x, m, args.nohtml)
     elif type(x) is dict:
         if "type" in x:
             if x['type'] == 'abilityDc' or x['type'] == 'abilityAttackMod':
                 skip = True
         if not skip:
             if "name" in x:
                 if 'subclassTitle' in d and d[
                         'subclassTitle'] and 'optional' in attributes:
                     if subclassname:
                         SubClassFeatureName = x[
                             'name'] + " (" + subclassname + ")"
                         flatten(SubClassFeatureName, m, args, "name")
                     else:
                         blank = ET.SubElement(m, 'text')
                         blank.text = ""
                         SubClassFeatureName = x['name']
                         flatten(SubClassFeatureName, m, args, "nametext")
                 else:
                     blank = ET.SubElement(m, 'text')
                     blank.text = ""
                     if 'type' in x and (x['type'] == 'entries'
                                         or x['type'] == 'inset'):
                         flatten(x['name'] + ":", m, args, "nametext")
                     else:
                         flatten(x['name'], m, args, "text")
             for a in x:
                 if a == "type" and x[a] == "list" and "style" in x and x[
                         "style"] == "list-hang-notitle":
                     blank = ET.SubElement(m, 'text')
                     blank.text = ""
                     for item in x["items"]:
                         flatten(item['name'], m, args, "text")
                         flatten(item['entry'], m, args, "list")
                     blank = ET.SubElement(m, 'text')
                     blank.text = ""
                 elif "colLabels" in x:
                     blank = ET.SubElement(m, 'text')
                     blank.text = ""
                     text = ET.SubElement(m, 'text')
                     text.text = " | ".join(
                         [utils.remove5eShit(y) for y in x['colLabels']])
                     for row in x['rows']:
                         rowthing = []
                         for r in row:
                             if isinstance(r, dict) and 'roll' in r:
                                 rowthing.append("{}-{}".format(
                                     r['roll']['min'], r['roll']['max']
                                 ) if 'min' in r['roll'] else str(
                                     r['roll']['exact']))
                             else:
                                 rowthing.append(
                                     utils.fixTags(str(r), m, args.nohtml))
                         text = ET.SubElement(m, 'text')
                         text.text = " | ".join(rowthing)
                 elif "type" in a and x[a] == "list":
                     flatten(x['items'], m, args, "list")
                 elif a == "entries":
                     flatten(x[a], m, args, "text")
     elif type(x) is list:
         i = 0
         for a in x:
             flatten(a, m, args, name)
             i += 1
Exemple #7
0
def parseSpell(m, compendium, args):
    spell = ET.SubElement(compendium, 'spell')
    name = ET.SubElement(spell, 'name')
    name.text = m['name']

    level = ET.SubElement(spell, 'level')
    level.text = str(m['level'])

    school = ET.SubElement(spell, 'school')
    if m['school'] == 'E':
        school.text = 'EN'
    elif m['school'] == 'V':
        school.text = 'EV'
    else:
        school.text = m['school']
    if m['school'] == 'P' and args.nohtml:
        spell.remove(school)

    if args.addimgs and os.path.isdir("./spells/"):
        if not os.path.isdir(os.path.join(args.tempdir, "spells")):
            os.mkdir(os.path.join(args.tempdir, "spells"))
        image = ET.SubElement(spell, 'image')
        if 'image' in m:
            artworkpath = m['image']
        else:
            artworkpath = None
        slug = slugify(m["name"])
        spellname = m["original_name"] if "original_name" in m else m["name"]
        if artworkpath and os.path.isfile("./img/" + artworkpath):
            artworkpath = "./img/" + artworkpath
        elif os.path.isfile("./img/spells/" + m["source"] + "/" + spellname +
                            ".jpg"):
            artworkpath = "./img/spells/" + m[
                "source"] + "/" + spellname + ".jpg"
        elif os.path.isfile("./img/spells/" + m["source"] + "/" + spellname +
                            ".png"):
            artworkpath = "./img/spells/" + m[
                "source"] + "/" + spellname + ".png"
        elif os.path.isfile("./img/" + m["source"] + "/" + spellname + ".png"):
            artworkpath = "./img/" + m["source"] + "/" + spellname + ".png"
        if artworkpath is not None:
            ext = os.path.splitext(artworkpath)[1]
            copyfile(artworkpath,
                     os.path.join(args.tempdir, "spells", slug + ext))
            image.text = slug + ext
        else:
            if m['school'] == 'E':
                artworkpath = "enchantment.png"
            elif m['school'] == 'V':
                artworkpath = "evocation.png"
            elif m['school'] == 'A':
                artworkpath = "abjuration.png"
            elif m['school'] == 'C':
                artworkpath = "conjuration.png"
            elif m['school'] == 'D':
                artworkpath = "divination.png"
            elif m['school'] == 'I':
                artworkpath = "illusion.png"
            elif m['school'] == 'N':
                artworkpath = "necromancy.png"
            elif m['school'] == 'T':
                artworkpath = "transmutation.png"
            elif m['school'] == 'P':
                artworkpath = "psionic.png"
            if not os.path.isfile(
                    os.path.join(args.tempdir, "spells", artworkpath)):
                copyfile(os.path.join("spells", artworkpath),
                         os.path.join(args.tempdir, "spells", artworkpath))
            image.text = artworkpath

    ritual = ET.SubElement(spell, 'ritual')
    if "meta" in m and "ritual" in m["meta"] and m["meta"]["ritual"]:
        ritual.text = "YES"
    else:
        ritual.text = "NO"

    time = ET.SubElement(spell, 'time')
    times = []
    for t in m["time"]:
        ttxt = "{} {}".format(t["number"], t["unit"])
        if t["unit"] == "bonus":
            ttxt += " action"
        if t["number"] > 1:
            ttxt += "s"
        times.append(ttxt)
    time.text = ", ".join(times)

    srange = ET.SubElement(spell, 'range')
    if m["range"]["type"] == "point":
        if "amount" not in m["range"]["distance"]:
            srange.text = m["range"]["distance"]["type"].title()
        else:
            srange.text = "{} {}".format(m["range"]["distance"]["amount"],
                                         m["range"]["distance"]["type"])
            if m["range"]["distance"]["amount"] == 1 and m["range"][
                    "distance"]["type"][-1:] == 's':
                srange.text = srange.text[:-1]
    elif m["range"]["type"] == "special":
        srange.text = "Special"
    else:
        dtype = m["range"]["distance"]["type"]
        if dtype == "feet":
            dtype = "foot"
        elif dtype[-1:] == 's':
            dtype = dtype[:-1]
        srange.text = "Self ({}-{} {})".format(
            m["range"]["distance"]["amount"], dtype, m["range"]["type"])

    components = ET.SubElement(spell, 'components')
    if "components" in m:
        componentsList = []
        for c in m["components"]:
            if type(m["components"][c]) is bool:
                componentsList.append(c.upper())
            elif type(m["components"][c]) is dict:
                componentsList.append("{} ({})".format(
                    c.upper(), m["components"][c]["text"]))
            else:
                componentsList.append("{} ({})".format(c.upper(),
                                                       m["components"][c]))
        components.text = ", ".join(componentsList)

    duration = ET.SubElement(spell, 'duration')
    durations = []
    for d in m["duration"]:
        if d["type"] == "timed":
            if "concentration" in d:
                dtxt = "Concentration, up to {} {}".format(
                    d["duration"]["amount"], d["duration"]["type"])
            else:
                dtxt = "{} {}".format(d["duration"]["amount"],
                                      d["duration"]["type"])
            if d["duration"]["amount"] > 1: dtxt += 's'
        elif d["type"] == "permanent":
            dtxt = "Until " + " or ".join(d["ends"])
            dtxt = dtxt.replace("dispel", "dispelled")
            dtxt = dtxt.replace("trigger", "triggered")
        elif d["type"] == "instant":
            dtxt = "Instantaneous"
        else:
            dtxt = d["type"]
        durations.append(dtxt)
    duration.text = ", ".join(durations)
    classes = ET.SubElement(spell, 'classes')
    classlist = []
    if "classes" in m and "fromClassList" in m["classes"]:
        for c in m["classes"]["fromClassList"]:
            if args.srd and c['source'] != 'PHB':
                continue
            if args.skipua and c['source'].startswith('UA'):
                continue
            if args.onlyofficial and not args.onlysrc:
                if c['source'] not in args.allowedsrc:
                    continue
            classlist.append(
                c["name"] +
                " (UA)" if c["source"].startswith("UA") else c["name"])
    if "classes" in m and "fromClassListVariant" in m["classes"]:
        for c in m["classes"]["fromClassListVariant"]:
            if args.srd and c['source'] != 'PHB':
                continue
            if args.skipua and c['source'].startswith('UA'):
                continue
            if args.onlyofficial and not args.onlysrc:
                if c['source'] not in args.allowedsrc:
                    continue
            if (c["name"] + " (UA)" if c["source"].startswith("UA") else
                    c["name"]) not in classlist:
                classlist.append(
                    c["name"] +
                    " (UA)" if c["source"].startswith("UA") else c["name"])
    if "classes" in m and "fromSubclass" in m["classes"]:
        for c in m["classes"]["fromSubclass"]:
            if args.srd:
                continue
            if args.skipua and (c["class"]["source"].startswith("UA")
                                or c["subclass"]["source"].startswith("UA")):
                continue
            if args.onlyofficial and not args.onlysrc:
                if c["class"]["source"] not in args.allowedsrc or c[
                        "subclass"]["source"] not in args.allowedsrc:
                    continue
            classlist.append("{} ({})".format(
                c["class"]["name"] + " (UA)" if
                c["class"]["source"].startswith("UA") else c["class"]["name"],
                c["subclass"]["name"]))
    classes.text = ", ".join(classlist)

    if "entriesHigherLevel" in m:
        if "entries" not in m: m["entries"] = []
        for higher in m["entriesHigherLevel"]:
            if args.nohtml:
                m["entries"].append("{}:".format(higher["name"]))
            else:
                m["entries"].append("<b>{}:</b>".format(higher["name"]))
            m["entries"] += higher["entries"]

    if 'source' in m and not args.srd:
        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source'], args), m['page']
        ) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(
            m['source'], args)

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                if "source" not in s:
                    continue
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"], args),
                    s["page"]) if 'page' in s and s[
                        "page"] != 0 else utils.getFriendlySource(
                            s["source"], args)
        if 'entries' in m:
            if args.nohtml:
                m['entries'].append("Source: {}".format(sourcetext))
            else:
                m['entries'].append("<i>Source: {}</i>".format(sourcetext))
        else:
            if args.nohtml:
                m['entries'] = "Source: {}".format(sourcetext)
            else:
                m['entries'] = ["<i>Source: {}</i>".format(sourcetext)]
        if not args.nohtml:
            source = ET.SubElement(spell, 'source')
            source.text = sourcetext
    bodyText = ET.SubElement(spell, 'text')
    bodyText.text = ""

    if 'entries' in m:
        for e in m['entries']:
            if "colLabels" in e:
                if 'caption' in e:
                    bodyText.text += "{}\n".format(e['caption'])
                bodyText.text += " | ".join(
                    [utils.remove5eShit(x) for x in e['colLabels']])
                bodyText.text += "\n"
                for row in e['rows']:
                    rowthing = []
                    for r in row:
                        if isinstance(r, dict) and 'roll' in r:
                            rowthing.append(
                                "{}-{}".format(r['roll']['min'], r['roll']
                                               ['max']) if 'min' in
                                r['roll'] else str(r['roll']['exact']))
                        else:
                            rowthing.append(
                                utils.fixTags(str(r), m, args.nohtml))
                    bodyText.text += " | ".join(rowthing) + "\n"
            elif "entries" in e:
                subentries = []
                for sube in e["entries"]:
                    if type(sube) == str:
                        subentries.append(utils.fixTags(sube, m, args.nohtml))
                    elif type(sube) == dict and "text" in sube:
                        subentries.append(
                            utils.fixTags(sube["text"], m, args.nohtml))
                if 'name' in e:
                    if args.nohtml:
                        bodyText.text += "{}: ".format(e['name'])
                    else:
                        bodyText.text += "<i>{}:</i> ".format(e['name'])
                bodyText.text += "\n".join(subentries) + "\n"
            else:
                if type(e) == dict and e[
                        "type"] == "list" and "style" in e and e[
                            "style"] == "list-hang-notitle":
                    for item in e["items"]:
                        bodyText.text += "• {}: {}".format(
                            item["name"],
                            utils.fixTags(item["entry"], m,
                                          args.nohtml)) + "\n"
                elif type(e) == dict and e["type"] == "list":
                    for item in e["items"]:
                        if "entries" in item:
                            subentries = []
                            for sube in item["entries"]:
                                if type(sube) == str:
                                    subentries.append(
                                        utils.fixTags(sube, m, args.nohtml))
                                elif type(sube) == dict and "text" in sube:
                                    subentries.append(
                                        utils.fixTags(sube["text"], m,
                                                      args.nohtml))
                                    bodyText.text += "\n".join(
                                        subentries) + "\n"
                        else:
                            bodyText.text += "• {}".format(
                                utils.fixTags(item, m, args.nohtml)) + "\n"
                else:
                    bodyText.text += utils.fixTags(e, m, args.nohtml) + "\n"

        bodyText.text = bodyText.text.rstrip()

        for match in re.finditer(
                r'(([0-9])+[dD]([0-9])+([ ]?[-+][ ]?[0-9]+)?)( +\+ +your spellcasting ability modifier| for each slot level above ([0-9]))?',
                bodyText.text):
            if match.group(5) and match.group(6):
                if "entriesHigherLevel" in m:
                    higherslot = ""
                    for higher in m["entriesHigherLevel"]:
                        higherslot += " ".join(higher["entries"])
                    for scale in re.finditer(
                            r'{@scaled(amage|ice) ([0-9]+)[dD]([0-9]+)(;([0-9]+)[dD]([0-9]+))?( +[-+] +[0-9]+)?\|(([0-9])-([0-9])|([0-9],?)*)\|([0-9]+)[dD]([0-9]+)}',
                            higherslot):
                        basecount = int(scale.group(2))
                        baseface = int(scale.group(3))
                        addcount = int(scale.group(12))
                        addface = int(scale.group(13))
                        base2count = None
                        base2face = None
                        if scale.group(4):
                            base2count = int(scale.group(5))
                            base2face = int(scale.group(6))
                        if scale.group(9) and scale.group(10):
                            scales = int(scale.group(10)) - int(scale.group(9))
                        else:
                            scales = len(scale.group(8).split(','))
                        for i in range(scales):
                            rolltext = "{}d{}{}".format(
                                basecount + ((i + 1) * addcount) if addface
                                == baseface else basecount, baseface,
                                scale.group(7) if scale.group(7) else "")
                            if not spell.find(
                                    "./[roll='{}']".format(rolltext)):
                                roll = ET.SubElement(spell, 'roll')
                                roll.text = rolltext.replace(' ', '')
                            if base2count and base2face:
                                rolltext = "{}d{}".format(
                                    base2count + ((i + 1) * addcount)
                                    if addface == base2face else base2count,
                                    base2face)
                                if not spell.find(
                                        "./[roll='{}']".format(rolltext)):
                                    roll = ET.SubElement(spell, 'roll')
                                    roll.text = rolltext.replace(' ', '')
                else:
                    mult = 1
                    for i in range(int(match.group(11)), 9):
                        rolltext = "{}d{}".format(
                            int(match.group(2)) * mult, match.group(3))
                        if not spell.find("./[roll='{}']".format(rolltext)):
                            roll = ET.SubElement(spell, 'roll')
                            roll.text = rolltext.replace(' ', '')
                        mult += 1
            elif match.group(5):
                if not spell.find("./[roll='{}+SPELL']".format(
                        match.group(1))):
                    roll = ET.SubElement(spell, 'roll')
                    roll.text = "{}+SPELL".format(match.group(1)).replace(
                        ' ', '')
            elif match.group(1):
                if not spell.find("./[roll='{}']".format(match.group(1))):
                    roll = ET.SubElement(spell, 'roll')
                    roll.text = "{}".format(match.group(1)).replace(' ', '')
Exemple #8
0
def parseRace(m, compendium, args):
    if '_copy' in m:
        if args.verbose:
            print("COPY: " + m['name'] + " from " + m['_copy']['name'] + " in " + m['_copy']['source'])
        xtrsrc = "./data/races.json"
        try:
            with open(xtrsrc) as f:
                d = json.load(f)
                f.close()
            mcpy = m
            for mn in d['race']:
                racefound = False
                if mn['name'] == mcpy['_copy']['name'] and mn['source'] == mcpy['_copy']['source']:
                    m = copy.deepcopy(mn)
                    m['name'] = mcpy['name']
                    m['source'] = mcpy['source']
                    if "otherSources" in mcpy:
                        m["otherSources"] = mcpy["otherSources"]
                    if 'page' in mcpy:
                        m['page'] = mcpy['page']
                    elif 'page' in m:
                        del m['page']
                    if '_mod' in mcpy['_copy']:
                        m = utils.modifyItem(m,mcpy['_copy']['_mod'])
                    racefound = True
                    break
            if not racefound:
                print("Could not find ",mcpy['_copy']['name'])
        except IOError as e:
            if args.verbose:
                print ("Could not load additional source ({}): {}".format(e.errno, e.strerror))
            return

    race = ET.SubElement(compendium, 'race')
    name = ET.SubElement(race, 'name')
    name.text = m['name']

    if 'entries' not in m:
        m['entries'] = []

    if 'source' in m and not args.srd:
        slug = slugify(m["name"])
        if args.addimgs and os.path.isdir("./img") and not os.path.isfile("./items/" + slug + ".png"):
            if not os.path.isdir("./items/"):
                os.mkdir("./items/")
            artworkpath = None
            if os.path.isfile("./img/items/" + m["name"] + ".jpg"):
                artworkpath = "./img/items/" + m["name"] + ".jpg"
            elif os.path.isfile("./img/items/" + m["name"] + ".png"):
                artworkpath = "./img/items/" + m["name"] + ".png"
            elif os.path.isfile("./img/items/" + m["source"] + "/" + m["name"] + ".png"):
                artworkpath = "./img/items/" + m["source"] + "/" + m["name"] + ".png"
            if artworkpath is not None:
                if args.verbose:
                    print("Converting Image: " + artworkpath)
                with Image(filename=artworkpath) as img:
                    img.format='png'
                    img.save(filename="./items/" + slug + ".png")
                    imagetag = ET.SubElement(race, 'image')
                    imagetag.text = slug + ".png"
        elif args.addimgs and os.path.isfile("./items/" + slug + ".png"):
            imagetag = ET.SubElement(race, 'image')
            imagetag.text = slug + ".png"

        sourcetext = "{} p. {}".format(
            utils.getFriendlySource(m['source'],args), m['page']) if 'page' in m and m['page'] != 0 else utils.getFriendlySource(m['source'],args)

        if 'otherSources' in m and m["otherSources"] is not None:
            for s in m["otherSources"]:
                sourcetext += ", "
                sourcetext += "{} p. {}".format(
                    utils.getFriendlySource(s["source"],args), s["page"]) if 'page' in s and s["page"] != 0 else utils.getFriendlySource(s["source"],args)
        if 'entries' in m:
            if args.nohtml:
                m['entries'].append("Source: {}".format(sourcetext))
            else:
                m['entries'].append("<i>Source: {}</i>".format(sourcetext))
        else:
            if args.nohtml:
                m['entries'] = ["Source: {}".format(sourcetext)]
            else:
                m['entries'] = ["<i>Source: {}</i>".format(sourcetext)]
        if not args.nohtml:
            source = ET.SubElement(race, 'source')
            source.text = sourcetext
    size = ET.SubElement(race, 'size')
    if m['size'] == 'V':
        size.text = 'M'
    else:
        size.text = m['size']
    
    speed = ET.SubElement(race, 'speed')
    if type(m['speed']) == dict:
        speed.text = str(m['speed']['walk'])
    elif m['speed'] != "Varies":
        speed.text = str(m['speed'])
    else:
        speed.text = "30"

    ability = ET.SubElement(race, 'ability')
    if 'ability' in m:
        abils = []
        for ab in m['ability']:
            for k,v in ab.items():
                if k != 'choose':
                    abils.append("{} {}".format(k,v).capitalize())
        ability.text = ", ".join(abils)


    prof = ET.SubElement(race, 'proficiency')
    if 'skillProficiencies' in m:
        profs = []
        for skill in m['skillProficiencies']:
            for k,v in skill.items():
                if k != 'choose' and k != 'tool':
                    if v:
                        profs.append(k.title())
        prof.text = ", ".join(profs)

    spell = ET.SubElement(race, 'spellAbility')
    trait = ET.SubElement(race, 'trait')
    name = ET.SubElement(trait, 'name')
    name.text = "Description"
    description = ET.SubElement(trait, 'text')
    description.text = ""
    
    if 'entries' in m:
        for e in m['entries']:
            if type(e) == dict:
                if 'name' in e:
                    trait = ET.SubElement(race, 'trait')
                    name = ET.SubElement(trait, 'name')
                    name.text = e['name']
                    text = ET.SubElement(trait, 'text')
                    text.text = ""
                else:
                    text = description
                if "colLabels" in e:
                    if 'caption' in e:
                        text.text += "{}\n".format(e['caption'])
                    text.text += " | ".join([utils.remove5eShit(x)
                                            for x in e['colLabels']])
                    text.text += "\n"
                    for row in e['rows']:
                        rowthing = []
                        for r in row:
                            if isinstance(r, dict) and 'roll' in r:
                                rowthing.append(
                                    "{}-{}".format(
                                        r['roll']['min'],
                                        r['roll']['max']) if 'min' in r['roll'] else str(
                                        r['roll']['exact']))
                            else:
                                rowthing.append(utils.fixTags(str(r),m,args.nohtml))
                        text.text += " | ".join(rowthing) + "\n"
                elif "entries" in e:
                    subentries = []
                    for sube in e["entries"]:
                        if type(sube) == str:
                            subentries.append(utils.fixTags(sube,m,args.nohtml))
                        elif type(sube) == dict and "text" in sube:
                            subentries.append(utils.fixTags(sube["text"],m,args.nohtml))
                        elif type(sube) == dict and sube["type"] == "list" and "style" in sube and sube["style"] == "list-hang-notitle":
                            for item in sube["items"]:
                                if type(item) == dict and 'type' in item and (item['type'] == 'item' or item['type'] == 'itemSpell'):
                                    if args.nohtml:
                                        subentries.append("• {} {}".format(item["name"] if item["name"].endswith(':') else item["name"] + ':',utils.fixTags(item["entry"],m,args.nohtml)))
                                    else:
                                        subentries.append("• <i>{}</i> {}".format(item["name"] if item["name"].endswith(':') else item["name"] + ':',utils.fixTags(item["entry"],m,args.nohtml)))
                                else:
                                    subentries.append("• {}".format(utils.fixTags(item,m,args.nohtml)))
                        elif type(sube) == dict and sube["type"] == "list":
                            for item in sube["items"]:
                                if type(item) == dict and "entries" in item:
                                    ssubentries = []                    
                                    for sse in item["entries"]:
                                        if type(sse) == str:
                                            ssubentries.append(utils.fixTags(sse,m,args.nohtml))
                                        elif type(sse) == dict and "text" in sse:
                                            ssubentries.append(utils.fixTags(sse["text"],m,args.nohtml))
                                        subentries.append("\n".join(ssubentries))
                                elif type(item) == dict and 'type' in item and item['type'] == 'item':
                                    if args.nohtml:
                                        subentries.append("• {}: {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                                    else:
                                        subentries.append("• <i>{}:</i> {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)))
                                else:
                                    subentries.append("• {}".format(utils.fixTags(item,m,args.nohtml)))
                        else:
                            if "colLabels" in sube:
                                tabletext = ""
                                if 'caption' in sube:
                                    text.text += "{}\n".format(sube['caption'])
                                tabletext += " | ".join([utils.remove5eShit(x)
                                                        for x in sube['colLabels']])
                                tabletext += "\n"
                                for row in sube['rows']:
                                    rowthing = []
                                    for r in row:
                                        if isinstance(r, dict) and 'roll' in r:
                                            rowthing.append(
                                                "{}-{}".format(
                                                    r['roll']['min'],
                                                    r['roll']['max']) if 'min' in r['roll'] else str(
                                                    r['roll']['exact']))
                                        else:
                                            rowthing.append(utils.fixTags(str(r),m,args.nohtml))
                                    tabletext += " | ".join(rowthing) + "\n"
                                subentries.append(tabletext)

                    text.text += "\n".join(subentries) + "\n"
                else:
                    if type(e) == dict and e["type"] == "list" and "style" in e and e["style"] == "list-hang-notitle":
                        for item in e["items"]:
                            if 'entries' in item and 'entry' not in item:
                                item['entry'] = ", ".join(item['entries'])
                            if args.nohtml:
                                text.text += "• {}: {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)) + "\n"
                            else:
                                text.text += "• <i>{}:</i> {}".format(item["name"],utils.fixTags(item["entry"],m,args.nohtml)) + "\n"
                    elif type(e) == dict and e["type"] == "list":
                        for item in e["items"]:
                            if "entries" in item:
                                subentries = []                    
                                for sube in item["entries"]:
                                    if type(sube) == str:
                                        subentries.append(utils.fixTags(sube,m,args.nohtml))
                                    elif type(sube) == dict and "text" in sube:
                                        subentries.append(utils.fixTags(sube["text"],m,args.nohtml))
                                    text.text += "\n".join(subentries) + "\n"
                            else:
                                text.text += "• {}".format(utils.fixTags(item,m,args.nohtml)) + "\n"
                match = re.search(r'(\w+) is your spellcasting ability', text.text)
                if match:
                    spell.text = match.group(1)
            else:
                description.text += utils.fixTags(e,m,args.nohtml) + "\n"

    description.text = description.text.rstrip()
Exemple #9
0
def parseEntries(m, args):
    bodyText = ""

    for e in m['entries']:
        if "colLabels" in e:
            if 'caption' in e:
                bodyText += "{}\n".format(e['caption'])

            bodyText += " | ".join(
                [utils.remove5eShit(x) for x in e['colLabels']])
            bodyText += "\n"
            for row in e['rows']:
                rowthing = []
                for r in row:
                    if isinstance(r, dict) and 'roll' in r:
                        rowthing.append(
                            "{}-{}".format(r['roll']['min'], r['roll']['max'])
                            if 'min' in r['roll'] else str(r['roll']['exact']))
                    else:
                        rowthing.append(utils.fixTags(str(r), m, args.nohtml))
                bodyText += " | ".join(rowthing) + "\n"
        elif "entries" in e:
            subentries = []
            if 'name' in e:
                if args.nohtml:
                    bodyText += "{}: ".format(e['name'])
                else:
                    bodyText += "<b>{}:</b> ".format(e['name'])
            for sube in e["entries"]:
                if type(sube) == str:
                    subentries.append(utils.fixTags(sube, m, args.nohtml))
                elif type(sube) == dict and "text" in sube:
                    subentries.append(
                        utils.fixTags(sube["text"], m, args.nohtml))
                elif type(sube) == dict and sube[
                        "type"] == "list" and "style" in sube and sube[
                            "style"] == "list-hang-notitle":
                    for item in sube["items"]:
                        if type(item) == dict and 'type' in item and item[
                                'type'] == 'item':
                            if args.nohtml:
                                subentries.append("• {}: {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)))
                            else:
                                subentries.append("• <i>{}:</i> {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)))
                        else:
                            subentries.append("• {}".format(
                                utils.fixTags(item, m, args.nohtml)))
                elif type(sube) == dict and sube["type"] == "list":
                    for item in sube["items"]:
                        if type(item) == dict and "entries" in item:
                            ssubentries = []
                            for sse in item["entries"]:
                                if type(sse) == str:
                                    ssubentries.append(
                                        utils.fixTags(sse, m, args.nohtml))
                                elif type(sse) == dict and "text" in sse:
                                    ssubentries.append(
                                        utils.fixTags(sse["text"], m,
                                                      args.nohtml))
                                subentries.append("\n".join(ssubentries))
                        elif type(item) == dict and 'type' in item and item[
                                'type'] == 'item':
                            if args.nohtml:
                                subentries.append("• {}: {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)))
                            else:
                                subentries.append("• <i>{}:</i> {}".format(
                                    item["name"],
                                    utils.fixTags(item["entry"], m,
                                                  args.nohtml)))
                        else:
                            subentries.append("• {}".format(
                                utils.fixTags(item, m, args.nohtml)))
            bodyText += "\n".join(subentries) + "\n"
        else:
            if type(e) == dict and e["type"] == "list" and "style" in e and e[
                    "style"] == "list-hang-notitle":
                for item in e["items"]:
                    if args.nohtml:
                        bodyText += "• {}: {}".format(
                            item["name"],
                            utils.fixTags(item["entry"], m,
                                          args.nohtml)) + "\n"
                    else:
                        bodyText += "• <i>{}:</i> {}".format(
                            item["name"],
                            utils.fixTags(item["entry"], m,
                                          args.nohtml)) + "\n"
            elif type(e) == dict and e["type"] == "list":
                for item in e["items"]:
                    if "entries" in item:
                        subentries = []
                        for sube in item["entries"]:
                            if type(sube) == str:
                                subentries.append(
                                    utils.fixTags(sube, m, args.nohtml))
                            elif type(sube) == dict and "text" in sube:
                                subentries.append(
                                    utils.fixTags(sube["text"], m,
                                                  args.nohtml))
                            bodyText += "\n".join(subentries) + "\n"
                    else:
                        bodyText += "• {}".format(
                            utils.fixTags(item, m, args.nohtml)) + "\n"
            else:
                bodyText += utils.fixTags(e, m, args.nohtml) + "\n"

    bodyText = bodyText.rstrip()
    return bodyText