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.")
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.")
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