Пример #1
0
def create_character_pdf(character, basename, flatten=False):
    # Prepare the list of fields
    class_level = (character.class_name + ' ' + str(character.level))
    fields = [
        # Character description
        ('CharacterName', character.name),
        ('ClassLevel', class_level),
        ('Background', character.background),
        ('PlayerName', character.player_name),
        ('Race ', str(character.race)),
        ('Alignment', character.alignment),
        ('XP', character.xp),
        # Abilities
        ('ProfBonus', mod_str(character.proficiency_bonus)),
        ('STRmod', str(character.strength.value)),
        ('STR', mod_str(character.strength.modifier)),
        ('DEXmod ', character.dexterity.value),
        ('DEX', mod_str(character.dexterity.modifier)),
        ('CONmod', character.constitution.value),
        ('CON', mod_str(character.constitution.modifier)),
        ('INTmod', character.intelligence.value),
        ('INT', mod_str(character.intelligence.modifier)),
        ('WISmod', character.wisdom.value),
        ('WIS', mod_str(character.wisdom.modifier)),
        ('CHamod', character.charisma.value),
        ('CHA', mod_str(character.charisma.modifier)),
        ('AC', character.armor_class),
        ('Initiative', mod_str(character.dexterity.modifier)),
        ('Speed', character.speed),
        ('Passive', 10 + character.perception),
        # Saving throws (proficiencies handled later)
        ('ST Strength', mod_str(character.strength.saving_throw)),
        ('ST Dexterity', mod_str(character.dexterity.saving_throw)),
        ('ST Constitution', mod_str(character.constitution.saving_throw)),
        ('ST Intelligence', mod_str(character.intelligence.saving_throw)),
        ('ST Wisdom', mod_str(character.wisdom.saving_throw)),
        ('ST Charisma', mod_str(character.charisma.saving_throw)),
        # Skills (proficiencies handled below)
        ('Acrobatics', mod_str(character.acrobatics)),
        ('Animal', mod_str(character.animal_handling)),
        ('Arcana', mod_str(character.arcana)),
        ('Athletics', mod_str(character.athletics)),
        ('Deception ', mod_str(character.deception)),
        ('History ', mod_str(character.history)),
        ('Insight', mod_str(character.insight)),
        ('Intimidation', mod_str(character.intimidation)),
        ('Investigation ', mod_str(character.investigation)),
        ('Medicine', mod_str(character.medicine)),
        ('Nature', mod_str(character.nature)),
        ('Perception ', mod_str(character.perception)),
        ('Performance', mod_str(character.performance)),
        ('Persuasion', mod_str(character.persuasian)),
        ('Religion', mod_str(character.religion)),
        ('SleightofHand', mod_str(character.sleight_of_hand)),
        ('Stealth ', mod_str(character.stealth)),
        ('Survival', mod_str(character.survival)),
        # Hit points
        ('HDTotal', character.hit_dice),
        ('HPMax', character.hp_max),
        # Personality traits and other features
        ('PersonalityTraits ', text_box(character.personality_traits)),
        ('Ideals', text_box(character.ideals)),
        ('Bonds', text_box(character.bonds)),
        ('Flaws', text_box(character.flaws)),
        ('Features and Traits', text_box(character.features_and_traits)),
        # Inventory
        ('CP', character.cp),
        ('SP', character.sp),
        ('EP', character.ep),
        ('GP', character.gp),
        ('PP', character.pp),
        ('Equipment', text_box(character.equipment)),
    ]
    # Check boxes for proficiencies
    ST_boxes = {
        'strength': 'Check Box 11',
        'dexterity': 'Check Box 18',
        'constitution': 'Check Box 19',
        'intelligence': 'Check Box 20',
        'wisdom': 'Check Box 21',
        'charisma': 'Check Box 22',
    }
    for ability in character.saving_throw_proficiencies:
        fields.append((ST_boxes[ability], 'Yes'))
    skill_boxes = {
        'acrobatics': 'Check Box 23',
        'animal_handling': 'Check Box 24',
        'arcana': 'Check Box 25',
        'athletics': 'Check Box 26',
        'deception': 'Check Box 27',
        'history': 'Check Box 28',
        'insight': 'Check Box 29',
        'intimidation': 'Check Box 30',
        'investigation': 'Check Box 31',
        'medicine': 'Check Box 32',
        'nature': 'Check Box 33',
        'perception': 'Check Box 34',
        'performance': 'Check Box 35',
        'persuasian': 'Check Box 36',
        'religion': 'Check Box 37',
        'sleight_of_hand': 'Check Box 38',
        'stealth': 'Check Box 39',
        'survival': 'Check Box 40',
    }
    # Add skill proficienies
    for skill in character.skill_proficiencies:
        fields.append((skill_boxes[skill.replace(' ', '_')], 'Yes'))
    # Add weapons
    weapon_fields = [
        ('Wpn Name', 'Wpn1 AtkBonus', 'Wpn1 Damage'),
        ('Wpn Name 2', 'Wpn2 AtkBonus ', 'Wpn2 Damage '),
        ('Wpn Name 3', 'Wpn3 AtkBonus  ', 'Wpn3 Damage '),
    ]
    for _fields, weapon in zip(weapon_fields, character.weapons):
        name_field, atk_field, dmg_field = _fields
        fields.append((name_field, weapon.name))
        fields.append((atk_field, mod_str(weapon.attack_bonus)))
        fields.append((dmg_field, f'{weapon.damage} {weapon.damage_type}'))
    # Other attack information
    attack_str = f'Armor: {character.armor}'
    attack_str += f'Shield: {character.shield}\n\n'
    attack_str += character.attacks_and_spellcasting
    fields.append(('AttacksSpellcasting', text_box(attack_str)))
    # Other proficiencies and languages
    prof_text = "Proficiencies:\n" + text_box(character.proficiencies_text)
    prof_text += "\n\nLanguages:\n" + text_box(character.languages)
    fields.append(('ProficienciesLang', prof_text))
    # Prepare the actual PDF
    dirname = os.path.dirname(os.path.abspath(__file__))
    src_pdf = os.path.join(dirname, 'blank-character-sheet-default.pdf')
    return make_pdf(fields,
                    src_pdf=src_pdf,
                    basename=basename,
                    flatten=flatten)
Пример #2
0
def create_spells_pdf(character, basename, flatten=False):
    class_level = (character.class_name + ' ' + str(character.level))
    spell_level = lambda x: (x or '')
    sc_ab = getattr(character, character.spellcasting_ability)
    fields = [
        ('Spellcasting Class 2', class_level),
        # ("SpellcastingAbility 2", character.spellcasting_ability.capitalize()),
        ("SpellcastingAbility 2", sc_ab.modifier),
        ('SpellSaveDC  2', character.spell_save_dc),
        ('SpellAtkBonus 2', mod_str(character.spell_attack_bonus)),
        # Number of spell slots
        ('SlotsTotal 19', spell_level(character.spell_slots(1))),
        ('SlotsTotal 20', spell_level(character.spell_slots(2))),
        ('SlotsTotal 21', spell_level(character.spell_slots(3))),
        ('SlotsTotal 22', spell_level(character.spell_slots(4))),
        ('SlotsTotal 23', spell_level(character.spell_slots(5))),
        ('SlotsTotal 24', spell_level(character.spell_slots(6))),
        ('SlotsTotal 25', spell_level(character.spell_slots(7))),
        ('SlotsTotal 26', spell_level(character.spell_slots(8))),
        ('SlotsTotal 27', spell_level(character.spell_slots(9))),
    ]
    # Cantrips
    cantrip_fields = (f'Spells 10{i}'
                      for i in (14, 16, 17, 18, 19, 20, 21, 22))
    cantrips = (spl for spl in character.spells if spl.level == 0)
    for spell, field_name in zip(cantrips, cantrip_fields):
        fields.append((field_name, str(spell)))
    # Spells for each level
    field_numbers = {
        1: (
            1015,
            1023,
            1024,
            1025,
            1026,
            1027,
            1028,
            1029,
            1030,
            1031,
            1032,
            1033,
        ),
        2: (
            1046,
            1034,
            1035,
            1036,
            1037,
            1038,
            1039,
            1040,
            1041,
            1042,
            1043,
            1044,
            1045,
        ),
        3: (
            1048,
            1047,
            1049,
            1050,
            1051,
            1052,
            1053,
            1054,
            1055,
            1056,
            1057,
            1058,
            1059,
        ),
        4: (
            1061,
            1060,
            1062,
            1063,
            1064,
            1065,
            1066,
            1067,
            1068,
            1069,
            1070,
            1071,
            1072,
        ),
        5: (
            1074,
            1073,
            1075,
            1076,
            1077,
            1078,
            1079,
            1080,
            1081,
        ),
        6: (
            1083,
            1082,
            1084,
            1085,
            1086,
            1087,
            1088,
            1089,
            1090,
        ),
        7: (
            1092,
            1091,
            1093,
            1094,
            1095,
            1096,
            1097,
            1098,
            1099,
        ),
        8: (
            10101,
            10100,
            10102,
            10103,
            10104,
            10105,
            10106,
        ),
        9: (10108, 10107, 10109, 101010, 101011, 101012, 101013),
    }
    prep_numbers = {
        1: (
            251,
            309,
            3010,
            3011,
            3012,
            3013,
            3014,
            3015,
            3016,
            3017,
            3018,
            3019,
        ),
        2: (
            313,
            310,
            3020,
            3021,
            3022,
            3023,
            3024,
            3025,
            3026,
            3027,
            3028,
            3029,
            3030,
        ),
        3: (
            315,
            314,
            3031,
            3032,
            3033,
            3034,
            3035,
            3036,
            3037,
            3038,
            3039,
            3040,
            3041,
        ),
        4: (
            317,
            316,
            3042,
            3043,
            3044,
            3045,
            3046,
            3047,
            3048,
            3049,
            3050,
            3051,
            3052,
        ),
        5: (
            319,
            318,
            3053,
            3054,
            3055,
            3056,
            3057,
            3058,
            3059,
        ),
        6: (
            321,
            320,
            3060,
            3061,
            3062,
            3063,
            3064,
            3065,
            3066,
        ),
        7: (
            323,
            322,
            3067,
            3068,
            3069,
            3070,
            3071,
            3072,
            3073,
        ),
        8: (
            325,
            324,
            3074,
            3075,
            3076,
            3077,
            3078,
        ),
        9: (
            327,
            326,
            3079,
            3080,
            3081,
            3082,
            3083,
        ),
    }
    for level in field_numbers.keys():
        spells = tuple(spl for spl in character.spells if spl.level == level)
        field_names = tuple(f'Spells {i}' for i in field_numbers[level])
        prep_names = tuple(f'Check Box {i}' for i in prep_numbers[level])
        for spell, field, chk_field in zip(spells, field_names, prep_names):
            fields.append((field, str(spell)))
            is_prepared = any(
                [isinstance(spell, Spl) for Spl in character.spells_prepared])
            fields.append((chk_field, is_prepared))
        # # Uncomment to post field names instead:
        # for field in field_names:
        #     fields.append((field, field))
    # Make the actual pdf
    dirname = os.path.dirname(os.path.abspath(__file__))
    src_pdf = os.path.join(dirname, 'blank-spell-sheet-default.pdf')
    make_pdf(fields, src_pdf=src_pdf, basename=basename, flatten=flatten)
Пример #3
0
 def test_mod_str(self):
     self.assertEqual(stats.mod_str(-3), "-3")
     self.assertEqual(stats.mod_str(0), "+0")
     self.assertEqual(stats.mod_str(2), "+2")
def create_character_pdf_template(character, basename, flatten=False):
    # Prepare the list of fields
    fields = {
        # Character description
        "CharacterName":
        character.name,
        "ClassLevel":
        character.classes_and_levels,
        "Background":
        str(character.background),
        "PlayerName":
        character.player_name,
        "Race ":
        str(character.race),
        "Alignment":
        character.alignment,
        "XP":
        str(character.xp),
        "Inspiration":
        str("Yes" if character.inspiration else "No"),
        # Abilities
        "ProfBonus":
        mod_str(character.proficiency_bonus),
        "STRmod":
        str(character.strength.value),
        "STR":
        mod_str(character.strength.modifier),
        "DEXmod ":
        str(character.dexterity.value),
        "DEX":
        mod_str(character.dexterity.modifier),
        "CONmod":
        str(character.constitution.value),
        "CON":
        mod_str(character.constitution.modifier),
        "INTmod":
        str(character.intelligence.value),
        "INT":
        mod_str(character.intelligence.modifier),
        "WISmod":
        str(character.wisdom.value),
        "WIS":
        mod_str(character.wisdom.modifier),
        "CHamod":
        str(character.charisma.value),
        "CHA":
        mod_str(character.charisma.modifier),
        "AC":
        str(character.armor_class),
        "Initiative":
        str(character.initiative),
        "Speed":
        str(character.speed),
        "Passive":
        10 + character.perception,
        # Saving throws (proficiencies handled later)
        "ST Strength":
        mod_str(character.strength.saving_throw),
        "ST Dexterity":
        mod_str(character.dexterity.saving_throw),
        "ST Constitution":
        mod_str(character.constitution.saving_throw),
        "ST Intelligence":
        mod_str(character.intelligence.saving_throw),
        "ST Wisdom":
        mod_str(character.wisdom.saving_throw),
        "ST Charisma":
        mod_str(character.charisma.saving_throw),
        # Skills (proficiencies handled below)
        "Acrobatics":
        mod_str(character.acrobatics),
        "Animal":
        mod_str(character.animal_handling),
        "Arcana":
        mod_str(character.arcana),
        "Athletics":
        mod_str(character.athletics),
        "Deception ":
        mod_str(character.deception),
        "History ":
        mod_str(character.history),
        "Insight":
        mod_str(character.insight),
        "Intimidation":
        mod_str(character.intimidation),
        "Investigation ":
        mod_str(character.investigation),
        "Medicine":
        mod_str(character.medicine),
        "Nature":
        mod_str(character.nature),
        "Perception ":
        mod_str(character.perception),
        "Performance":
        mod_str(character.performance),
        "Persuasion":
        mod_str(character.persuasion),
        "Religion":
        mod_str(character.religion),
        "SleightofHand":
        mod_str(character.sleight_of_hand),
        "Stealth ":
        mod_str(character.stealth),
        "Survival":
        mod_str(character.survival),
        # Hit points
        "HDTotal":
        character.hit_dice,
        "HPMax":
        str(character.hp_max),
        # Personality traits and other features
        "PersonalityTraits ":
        text_box(character.personality_traits),
        "Ideals":
        text_box(character.ideals),
        "Bonds":
        text_box(character.bonds),
        "Flaws":
        text_box(character.flaws),
        "Features and Traits":
        text_box(character.features_text + character.features_and_traits),
        # Inventory
        "CP":
        character.cp,
        "SP":
        character.sp,
        "EP":
        character.ep,
        "GP":
        character.gp,
        "PP":
        character.pp,
        "Equipment":
        text_box(character.magic_items_text + character.equipment),
    }
    # Check boxes for proficiencies
    ST_boxes = {
        "strength": "Check Box 11",
        "dexterity": "Check Box 18",
        "constitution": "Check Box 19",
        "intelligence": "Check Box 20",
        "wisdom": "Check Box 21",
        "charisma": "Check Box 22",
    }
    for ability in character.saving_throw_proficiencies:
        fields[ST_boxes[ability]] = CHECKBOX_ON
    # Add skill proficiencies
    skill_boxes = {
        "acrobatics": "Check Box 23",
        "animal_handling": "Check Box 24",
        "arcana": "Check Box 25",
        "athletics": "Check Box 26",
        "deception": "Check Box 27",
        "history": "Check Box 28",
        "insight": "Check Box 29",
        "intimidation": "Check Box 30",
        "investigation": "Check Box 31",
        "medicine": "Check Box 32",
        "nature": "Check Box 33",
        "perception": "Check Box 34",
        "performance": "Check Box 35",
        "persuasion": "Check Box 36",
        "religion": "Check Box 37",
        "sleight_of_hand": "Check Box 38",
        "stealth": "Check Box 39",
        "survival": "Check Box 40",
    }
    for skill in character.skill_proficiencies:
        try:
            fields[skill_boxes[skill.replace(" ", "_").lower()]] = CHECKBOX_ON
        except KeyError:
            raise KeyError(f"Unknown skill: '{skill}'")
    # Add weapons
    weapon_fields = [
        ("Wpn Name", "Wpn1 AtkBonus", "Wpn1 Damage"),
        ("Wpn Name 2", "Wpn2 AtkBonus ", "Wpn2 Damage "),
        ("Wpn Name 3", "Wpn3 AtkBonus  ", "Wpn3 Damage "),
    ]
    if len(character.weapons) == 0:
        character.wield_weapon("unarmed")
    for _fields, weapon in zip(weapon_fields, character.weapons):
        name_field, atk_field, dmg_field = _fields
        fields[name_field] = weapon.name
        fields[atk_field] = "{:+d}".format(weapon.attack_modifier)
        fields[dmg_field] = f"{weapon.damage}/{weapon.damage_type}"
    # Other attack information
    attack = []
    if character.armor:
        attack.append(f"Armor: {character.armor}")
    if character.shield:
        attack.append(f"Shield: {character.shield}")
    attack.append(character.attacks_and_spellcasting)
    attack_str = "\n\n".join(attack)
    fields["AttacksSpellcasting"] = text_box(attack_str)
    # Other proficiencies and languages
    prof_text = "Proficiencies:\n" + text_box(character.proficiencies_text)
    prof_text += "\n\nLanguages:\n" + text_box(character.languages)
    fields["ProficienciesLang"] = prof_text
    # Prepare the actual PDF
    dirname = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                           "forms/")
    src_pdf = os.path.join(dirname, "blank-character-sheet-default.pdf")
    return make_pdf(fields,
                    src_pdf=src_pdf,
                    basename=basename,
                    flatten=flatten)
def create_spells_pdf_template(character, basename, flatten=False):
    classes_and_levels = " / ".join(
        [c.name + " " + str(c.level) for c in character.spellcasting_classes])
    abilities = " / ".join([
        c.spellcasting_ability.upper()[:3]
        for c in character.spellcasting_classes
    ])
    DCs = " / ".join([
        str(character.spell_save_dc(c)) for c in character.spellcasting_classes
    ])
    bonuses = " / ".join([
        mod_str(character.spell_attack_bonus(c))
        for c in character.spellcasting_classes
    ])

    def spell_level(x):
        return x or 0

    fields = {
        "Spellcasting Class 2": classes_and_levels,
        "SpellcastingAbility 2": abilities,
        "SpellSaveDC  2": DCs,
        "SpellAtkBonus 2": bonuses,
        # Number of spell slots
        "SlotsTotal 19": spell_level(character.spell_slots(1)),
        "SlotsTotal 20": spell_level(character.spell_slots(2)),
        "SlotsTotal 21": spell_level(character.spell_slots(3)),
        "SlotsTotal 22": spell_level(character.spell_slots(4)),
        "SlotsTotal 23": spell_level(character.spell_slots(5)),
        "SlotsTotal 24": spell_level(character.spell_slots(6)),
        "SlotsTotal 25": spell_level(character.spell_slots(7)),
        "SlotsTotal 26": spell_level(character.spell_slots(8)),
        "SlotsTotal 27": spell_level(character.spell_slots(9)),
    }
    # Cantrips
    cantrip_fields = (f"Spells 10{i}"
                      for i in (14, 16, 17, 18, 19, 20, 21, 22))
    cantrips = (spl for spl in character.spells if spl.level == 0)
    for spell, field_name in zip(cantrips, cantrip_fields):
        fields[field_name] = str(spell)
    # Spells for each level
    field_numbers = {
        1: (
            1015,
            1023,
            1024,
            1025,
            1026,
            1027,
            1028,
            1029,
            1030,
            1031,
            1032,
            1033,
        ),
        2: (
            1046,
            1034,
            1035,
            1036,
            1037,
            1038,
            1039,
            1040,
            1041,
            1042,
            1043,
            1044,
            1045,
        ),
        3: (
            1048,
            1047,
            1049,
            1050,
            1051,
            1052,
            1053,
            1054,
            1055,
            1056,
            1057,
            1058,
            1059,
        ),
        4: (
            1061,
            1060,
            1062,
            1063,
            1064,
            1065,
            1066,
            1067,
            1068,
            1069,
            1070,
            1071,
            1072,
        ),
        5: (
            1074,
            1073,
            1075,
            1076,
            1077,
            1078,
            1079,
            1080,
            1081,
        ),
        6: (
            1083,
            1082,
            1084,
            1085,
            1086,
            1087,
            1088,
            1089,
            1090,
        ),
        7: (
            1092,
            1091,
            1093,
            1094,
            1095,
            1096,
            1097,
            1098,
            1099,
        ),
        8: (
            10101,
            10100,
            10102,
            10103,
            10104,
            10105,
            10106,
        ),
        9: (10108, 10107, 10109, 101010, 101011, 101012, 101013),
    }
    prep_numbers = {
        1: (
            251,
            309,
            3010,
            3011,
            3012,
            3013,
            3014,
            3015,
            3016,
            3017,
            3018,
            3019,
        ),
        2: (
            313,
            310,
            3020,
            3021,
            3022,
            3023,
            3024,
            3025,
            3026,
            3027,
            3028,
            3029,
            3030,
        ),
        3: (
            315,
            314,
            3031,
            3032,
            3033,
            3034,
            3035,
            3036,
            3037,
            3038,
            3039,
            3040,
            3041,
        ),
        4: (
            317,
            316,
            3042,
            3043,
            3044,
            3045,
            3046,
            3047,
            3048,
            3049,
            3050,
            3051,
            3052,
        ),
        5: (
            319,
            318,
            3053,
            3054,
            3055,
            3056,
            3057,
            3058,
            3059,
        ),
        6: (
            321,
            320,
            3060,
            3061,
            3062,
            3063,
            3064,
            3065,
            3066,
        ),
        7: (
            323,
            322,
            3067,
            3068,
            3069,
            3070,
            3071,
            3072,
            3073,
        ),
        8: (
            325,
            324,
            3074,
            3075,
            3076,
            3077,
            3078,
        ),
        9: (
            327,
            326,
            3079,
            3080,
            3081,
            3082,
            3083,
        ),
    }
    for level in field_numbers.keys():
        spells = tuple(spl for spl in character.spells if spl.level == level)
        field_names = tuple(f"Spells {i}" for i in field_numbers[level])
        prep_names = tuple(f"Check Box {i}" for i in prep_numbers[level])
        for spell, field, chk_field in zip(spells, field_names, prep_names):
            fields[field] = str(spell)
            is_prepared = any(
                [spell == Spl for Spl in character.spells_prepared])
            fields[chk_field] = CHECKBOX_ON if is_prepared else CHECKBOX_OFF
        # # Uncomment to post field names instead:
        # for field in field_names:
        #     fields.append((field, field))
    # Make the actual pdf
    dirname = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                           "forms/")
    src_pdf = os.path.join(dirname, "blank-spell-sheet-default.pdf")
    make_pdf(fields, src_pdf=src_pdf, basename=basename, flatten=flatten)
Пример #6
0
def create_character_pdf(character, basename, flatten=False):
    # Prepare the list of fields
    fields = {
        # Character description
        'CharacterName':
        character.name,
        'ClassLevel':
        character.classes_and_levels,
        'Background':
        str(character.background),
        'PlayerName':
        character.player_name,
        'Race ':
        str(character.race),
        'Alignment':
        character.alignment,
        'XP':
        str(character.xp),
        'Inspiration':
        str('Yes' if character.inspiration else 'No'),
        # Abilities
        'ProfBonus':
        mod_str(character.proficiency_bonus),
        'STRmod':
        str(character.strength.value),
        'STR':
        mod_str(character.strength.modifier),
        'DEXmod ':
        str(character.dexterity.value),
        'DEX':
        mod_str(character.dexterity.modifier),
        'CONmod':
        str(character.constitution.value),
        'CON':
        mod_str(character.constitution.modifier),
        'INTmod':
        str(character.intelligence.value),
        'INT':
        mod_str(character.intelligence.modifier),
        'WISmod':
        str(character.wisdom.value),
        'WIS':
        mod_str(character.wisdom.modifier),
        'CHamod':
        str(character.charisma.value),
        'CHA':
        mod_str(character.charisma.modifier),
        'AC':
        str(character.armor_class),
        'Initiative':
        str(character.initiative),
        'Speed':
        str(character.speed),
        'Passive':
        10 + character.perception,
        # Saving throws (proficiencies handled later)
        'ST Strength':
        mod_str(character.strength.saving_throw),
        'ST Dexterity':
        mod_str(character.dexterity.saving_throw),
        'ST Constitution':
        mod_str(character.constitution.saving_throw),
        'ST Intelligence':
        mod_str(character.intelligence.saving_throw),
        'ST Wisdom':
        mod_str(character.wisdom.saving_throw),
        'ST Charisma':
        mod_str(character.charisma.saving_throw),
        # Skills (proficiencies handled below)
        'Acrobatics':
        mod_str(character.acrobatics),
        'Animal':
        mod_str(character.animal_handling),
        'Arcana':
        mod_str(character.arcana),
        'Athletics':
        mod_str(character.athletics),
        'Deception ':
        mod_str(character.deception),
        'History ':
        mod_str(character.history),
        'Insight':
        mod_str(character.insight),
        'Intimidation':
        mod_str(character.intimidation),
        'Investigation ':
        mod_str(character.investigation),
        'Medicine':
        mod_str(character.medicine),
        'Nature':
        mod_str(character.nature),
        'Perception ':
        mod_str(character.perception),
        'Performance':
        mod_str(character.performance),
        'Persuasion':
        mod_str(character.persuasion),
        'Religion':
        mod_str(character.religion),
        'SleightofHand':
        mod_str(character.sleight_of_hand),
        'Stealth ':
        mod_str(character.stealth),
        'Survival':
        mod_str(character.survival),
        # Hit points
        'HDTotal':
        character.hit_dice,
        'HPMax':
        str(character.hp_max),
        # Personality traits and other features
        'PersonalityTraits ':
        text_box(character.personality_traits),
        'Ideals':
        text_box(character.ideals),
        'Bonds':
        text_box(character.bonds),
        'Flaws':
        text_box(character.flaws),
        'Features and Traits':
        text_box(character.features_text + character.features_and_traits),
        # Inventory
        'CP':
        character.cp,
        'SP':
        character.sp,
        'EP':
        character.ep,
        'GP':
        character.gp,
        'PP':
        character.pp,
        'Equipment':
        text_box(character.magic_items_text + character.equipment),
    }
    # Check boxes for proficiencies
    ST_boxes = {
        'strength': 'Check Box 11',
        'dexterity': 'Check Box 18',
        'constitution': 'Check Box 19',
        'intelligence': 'Check Box 20',
        'wisdom': 'Check Box 21',
        'charisma': 'Check Box 22',
    }
    for ability in character.saving_throw_proficiencies:
        fields[ST_boxes[ability]] = CHECKBOX_ON
    # Add skill proficiencies
    skill_boxes = {
        'acrobatics': 'Check Box 23',
        'animal_handling': 'Check Box 24',
        'arcana': 'Check Box 25',
        'athletics': 'Check Box 26',
        'deception': 'Check Box 27',
        'history': 'Check Box 28',
        'insight': 'Check Box 29',
        'intimidation': 'Check Box 30',
        'investigation': 'Check Box 31',
        'medicine': 'Check Box 32',
        'nature': 'Check Box 33',
        'perception': 'Check Box 34',
        'performance': 'Check Box 35',
        'persuasion': 'Check Box 36',
        'religion': 'Check Box 37',
        'sleight_of_hand': 'Check Box 38',
        'stealth': 'Check Box 39',
        'survival': 'Check Box 40',
    }
    for skill in character.skill_proficiencies:
        try:
            fields[skill_boxes[skill.replace(' ', '_').lower()]] = CHECKBOX_ON
        except KeyError:
            raise KeyError(f"Unknown skill: '{skill}'")
    # Add weapons
    weapon_fields = [
        ('Wpn Name', 'Wpn1 AtkBonus', 'Wpn1 Damage'),
        ('Wpn Name 2', 'Wpn2 AtkBonus ', 'Wpn2 Damage '),
        ('Wpn Name 3', 'Wpn3 AtkBonus  ', 'Wpn3 Damage '),
    ]
    if len(character.weapons) == 0:
        character.wield_weapon('unarmed')
    for _fields, weapon in zip(weapon_fields, character.weapons):
        name_field, atk_field, dmg_field = _fields
        fields[name_field] = weapon.name
        fields[atk_field] = '{:+d}'.format(weapon.attack_modifier)
        fields[dmg_field] = f'{weapon.damage}/{weapon.damage_type}'
    # Other attack information
    attack = []
    if character.armor:
        attack.append(f'Armor: {character.armor}')
    if character.shield:
        attack.append(f'Shield: {character.shield}')
    attack.append(character.attacks_and_spellcasting)
    attack_str = '\n\n'.join(attack)
    fields['AttacksSpellcasting'] = text_box(attack_str)
    # Other proficiencies and languages
    prof_text = "Proficiencies:\n" + text_box(character.proficiencies_text)
    prof_text += "\n\nLanguages:\n" + text_box(character.languages)
    fields['ProficienciesLang'] = prof_text
    # Prepare the actual PDF
    dirname = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                           'forms/')
    src_pdf = os.path.join(dirname, 'blank-character-sheet-default.pdf')
    return make_pdf(fields,
                    src_pdf=src_pdf,
                    basename=basename,
                    flatten=flatten)
Пример #7
0
 def test_mod_str(self):
     self.assertEqual(stats.mod_str(-3), '-3')
     self.assertEqual(stats.mod_str(0), '0')
     self.assertEqual(stats.mod_str(2), '+2')