Esempio n. 1
0
    async def customcounter_create(self, ctx, name, *args):
        """Creates a new custom counter.
        __Valid Arguments__
        `-reset <short|long|none>` - Counter will reset to max on a short/long rest, or not ever when "none". Default - will reset on a call of `!cc reset`.
        `-max <max value>` - The maximum value of the counter.
        `-min <min value>` - The minimum value of the counter.
        `-type <bubble|default>` - Whether the counter displays bubbles to show remaining uses or numbers. Default - numbers."""
        character: Character = await Character.from_ctx(ctx)

        conflict = next(
            (c
             for c in character.consumables if c.name.lower() == name.lower()),
            None)
        if conflict:
            if await confirm(
                    ctx,
                    "Warning: This will overwrite an existing consumable. Continue?"
            ):
                character.consumables.remove(conflict)
            else:
                return await ctx.send("Overwrite unconfirmed. Aborting.")

        args = argparse(args)
        _reset = args.last('reset')
        _max = args.last('max')
        _min = args.last('min')
        _type = args.last('type')
        try:
            new_counter = CustomCounter.new(character,
                                            name,
                                            maxv=_max,
                                            minv=_min,
                                            reset=_reset,
                                            display_type=_type)
            character.consumables.append(new_counter)
            await character.commit(ctx)
        except InvalidArgument as e:
            return await ctx.send(f"Failed to create counter: {e}")
        else:
            await ctx.send(f"Custom counter created.")
Esempio n. 2
0
    async def customcounter_create(self, ctx, name, *args):
        """
        Creates a new custom counter.
        __Valid Arguments__
        `-title <title>` - Sets the title for the output when modifying the counter. `[name]` will be replaced with the player's name.
        `-desc <desc>` - Sets the description when setting or viewing the counter.
        `-reset <short|long|none>` - Counter will reset to max on a short/long rest, or not ever when "none". Default - will reset on a call of `!cc reset`.
        `-max <max value>` - The maximum value of the counter.
        `-min <min value>` - The minimum value of the counter.
        `-type <bubble|default>` - Whether the counter displays bubbles to show remaining uses or numbers. Default - numbers.
        `-resetto <value>` - The value to reset the counter to. Default - maximum.
        `-resetby <value>` - Rather than resetting to a certain value, modify the counter by this much per reset. Supports dice.
        """  # noqa: E501
        character: Character = await Character.from_ctx(ctx)

        conflict = next((c for c in character.consumables if c.name.lower() == name.lower()), None)
        if conflict:
            if await confirm(ctx, "Warning: This will overwrite an existing consumable. Continue? (Reply with yes/no)"):
                character.consumables.remove(conflict)
            else:
                return await ctx.send("Overwrite unconfirmed. Aborting.")

        args = argparse(args)
        _reset = args.last('reset')
        _max = args.last('max')
        _min = args.last('min')
        _type = args.last('type')
        reset_to = args.last('resetto')
        reset_by = args.last('resetby')
        title = args.last('title')
        desc = args.last('desc')
        try:
            new_counter = CustomCounter.new(character, name, maxv=_max, minv=_min, reset=_reset, display_type=_type,
                                            reset_to=reset_to, reset_by=reset_by, title=title, desc=desc)
            character.consumables.append(new_counter)
            await character.commit(ctx)
        except InvalidArgument as e:
            return await ctx.send(f"Failed to create counter: {e}")
        else:
            await ctx.send("Custom counter created.")
Esempio n. 3
0
def migrate(character):
    name = character['stats']['name']
    sheet_type = character.get('type')
    import_version = character.get('version')
    print(f"Migrating {name} - {sheet_type} v{import_version}")

    owner = character['owner']
    upstream = character['upstream']
    active = character['active']

    description = character['stats'].get('description', "No description")
    image = character['stats']['image']

    stats = {
        "prof_bonus": character['stats']['proficiencyBonus'],
        "strength": character['stats']['strength'],
        "dexterity": character['stats']['dexterity'],
        "constitution": character['stats']['constitution'],
        "intelligence": character['stats']['intelligence'],
        "wisdom": character['stats']['wisdom'],
        "charisma": character['stats']['charisma']
    }

    # classes
    classes = {}
    for c, l in character['levels'].items():
        if c.endswith("Level"):
            classes[c[:-5]] = l
    for cls, lvl in list(classes.items())[:]:
        if any(inv in cls for inv in ".$"):
            classes.pop(cls)
    levels = {"total_level": character['levels']['level'], "classes": classes}

    # attacks
    attacks = []
    for a in character['attacks']:
        try:
            bonus = int(a['attackBonus'])
            bonus_calc = None
        except (ValueError, TypeError):
            bonus = None
            bonus_calc = a['attackBonus']
        atk = {
            "name": a['name'],
            "bonus": bonus,
            "damage": a['damage'],
            "details": a.get('details'),
            "bonus_calc": bonus_calc
        }
        attacks.append(atk)

    # skills and saves
    skills = {}
    for skill_name in SKILL_NAMES:
        value = character['skills'][skill_name]
        skefct = character.get('skill_effects', {}).get(skill_name)
        adv = True if skefct == 'adv' else False if skefct == 'dis' else None
        skl = Skill(value, 0, 0, adv)
        skills[skill_name] = skl.to_dict()

    saves = {}
    for save_name in SAVE_NAMES:
        value = character['saves'][save_name]
        skefct = character.get('skill_effects', {}).get(save_name)
        adv = True if skefct == 'adv' else False if skefct == 'dis' else None
        skl = Skill(value, 0, 0, adv)
        saves[save_name] = skl.to_dict()

    # combat
    resistances = {
        "resist": character.get('resist', []),
        "immune": character.get('immune', []),
        "vuln": character.get('vuln', [])
    }
    ac = character.get('armor', 10)
    max_hp = character.get('hp',
                           4)  # you get 4 hp if your character is that old
    hp = character.get('consumables', {}).get('hp', {}).get('value', max_hp)
    temp_hp = character.get('consumables', {}).get('temphp',
                                                   {}).get('value', 0)

    cvars = character.get('cvars', {})
    options = {"options": character.get('settings', {})}

    # overrides
    override_attacks = []
    for a in character.get('overrides', {}).get('attacks', []):
        try:
            bonus = int(a['attackBonus'])
            bonus_calc = None
        except (ValueError, TypeError):
            bonus = None
            bonus_calc = a['attackBonus']
        atk = {
            "name": a['name'],
            "bonus": bonus,
            "damage": a['damage'],
            "details": a['details'],
            "bonus_calc": bonus_calc
        }
        override_attacks.append(atk)
    override_spells = []
    for old_spell in character.get('overrides', {}).get('spells', []):
        if isinstance(old_spell, dict):
            spl = SpellbookSpell(old_spell['name'], old_spell['strict'])
        else:
            spl = SpellbookSpell(old_spell, True)
        override_spells.append(spl.to_dict())
    overrides = {
        "desc": character.get('overrides', {}).get('desc'),
        "image": character.get('overrides', {}).get('image'),
        "attacks": override_attacks,
        "spells": override_spells
    }

    # other things
    consumables = []
    for cname, cons in character.get('consumables', {}).get('custom',
                                                            {}).items():
        value = cons['value']
        minv = cons.get('min')
        maxv = cons.get('max')
        reset = cons.get('reset')
        display_type = cons.get('type')
        live_id = cons.get('live')
        counter = CustomCounter(None, cname, value, minv, maxv, reset,
                                display_type, live_id)
        consumables.append(counter.to_dict())

    death_saves = {
        "successes":
        character.get('consumables', {}).get('deathsaves',
                                             {}).get('success',
                                                     {}).get('value', 0),
        "fails":
        character.get('consumables', {}).get('deathsaves',
                                             {}).get('fail',
                                                     {}).get('value', 0)
    }

    # spellcasting
    slots = {}
    max_slots = {}
    for l in range(1, 10):
        slots[str(l)] = character.get('consumables',
                                      {}).get('spellslots',
                                              {}).get(str(l),
                                                      {}).get('value', 0)
        max_slots[str(l)] = character.get('spellbook',
                                          {}).get('spellslots',
                                                  {}).get(str(l), 0)
    spells = []
    for old_spell in character.get('spellbook', {}).get('spells', []):
        if isinstance(old_spell, dict):
            spl = SpellbookSpell(old_spell['name'], old_spell['strict'])
        else:
            spl = SpellbookSpell(old_spell, True)
        spells.append(spl.to_dict())
    spellbook = {
        "slots": slots,
        "max_slots": max_slots,
        "spells": spells,
        "dc": character.get('spellbook', {}).get('dc'),
        "sab": character.get('spellbook', {}).get('attackBonus'),
        "caster_level": character['levels']['level']
    }

    live = 'dicecloud' if character.get('live') else None
    race = character.get('race')
    background = character.get('background')

    char = Character(owner, upstream, active, sheet_type, import_version, name,
                     description, image, stats, levels, attacks, skills,
                     resistances, saves, ac, max_hp, hp, temp_hp, cvars,
                     options, overrides, consumables, death_saves, spellbook,
                     live, race, background)
    return char