Example #1
0
async def mods(p: Player, c: Messageable, msg: Sequence[str]) -> str:
    if isinstance(c, Channel) or c.id != 1:
        return 'This command can only be used in DM with Aika.'

    if not p.last_np:
        return 'Please /np a map first!'

    msg = ''.join(msg).replace(' ', '')
    if msg[0] == '+': # remove +
        msg = msg[1:]

    mods = Mods.from_str(msg)

    if mods not in p.last_np.pp_cache:
        # cach
        await p.last_np.cache_pp(mods)

    # Since this is a DM to the bot, we should
    # send back a list of general PP values.
    # TODO: !acc and !mods in commands to
    #       modify these values :P
    _msg = [p.last_np.embed]
    if mods:
        _msg.append(f'{mods!r}')

    msg = f"{' '.join(_msg)}: " + ' | '.join(
        f'{acc}%: {pp:.2f}pp'
        for acc, pp in zip(
            (90, 95, 98, 99, 100),
            p.last_np.pp_cache[mods]
        ))

    return msg
Example #2
0
async def _with(p: Player, c: Messageable, msg: Sequence[str]) -> str:
    """Specify custom accuracy & mod combinations with `/np`."""
    if isinstance(c, Channel) or c.id != 1:
        return 'This command can only be used in DM with Aika.'

    if not p.last_np:
        return 'Please /np a map first!'

    # +?<mods> <acc>%?
    if 1 < len(msg) > 2:
        return 'Invalid syntax: !with <mods/acc> ...'

    mods = acc = None

    for param in (p.strip('+%') for p in msg):
        if cmyui._isdecimal(param, _float=True):
            acc = float(param)
        elif ~len(param) & 1: # len(param) % 2 == 0
            mods = Mods.from_str(param)
        else:
            return 'Invalid syntax: !with <mods/acc> ...'

    _msg = [p.last_np.embed]
    if not mods:
        mods = Mods.NOMOD

    _msg.append(repr(mods))

    if acc:
        # they're requesting pp for specified acc value.
        async with Owoppai(p.last_np.id, acc=acc, mods=mods) as owo:
            await owo.calc()
            pp_values = [(owo.acc, owo.pp)]
    else:
        # they're requesting pp for general accuracy values.
        if mods not in p.last_np.pp_cache:
            # cache
            await p.last_np.cache_pp(mods)

        pp_values = zip(
            (90, 95, 98, 99, 100),
            p.last_np.pp_cache[mods]
        )

    pp_msg = ' | '.join(f'{acc:.2f}%: {pp:.2f}pp'
                        for acc, pp in pp_values)
    return f"{' '.join(_msg)}: {pp_msg}"
Example #3
0
async def mp_mods(p: 'Player', m: 'Match', msg: Sequence[str]) -> str:
    """Set the current match's mods, from string form."""
    if len(msg) != 1 or not ~len(msg[0]) & 1:
        return 'Invalid syntax: !mp mods <mods>'

    mods = Mods.from_str(msg[0])

    if m.freemods:
        if p is m.host:
            # allow host to set speed-changing mods.
            m.mods = mods & Mods.SPEED_CHANGING

        # set slot mods
        m.get_slot(p).mods = mods & ~Mods.SPEED_CHANGING
    else:
        # not freemods, set match mods.
        m.mods = mods

    m.enqueue_state()
    return 'Match mods updated.'
Example #4
0
async def mp_mods(p: Player, m: Match, msg: Sequence[str]) -> str:
    """Set `m`'s mods, from string form."""
    if len(msg) != 1 or not ~len(msg[0]) & 1: # len(msg[0]) % 2 == 0
        return 'Invalid syntax: !mp mods <mods>'

    mods = Mods.from_str(msg[0])

    if m.freemods:
        if p.id == m.host.id:
            # allow host to set speed-changing mods.
            m.mods = mods & Mods.SPEED_CHANGING

        # set slot mods
        m.get_slot(p).mods = mods & ~Mods.SPEED_CHANGING
    else:
        # not freemods, set match mods.
        m.mods = mods

    m.enqueue(packets.updateMatch(m))
    return 'Match mods updated.'
Example #5
0
async def _with(p: 'Player', c: Messageable, msg: Sequence[str]) -> str:
    """Specify custom accuracy & mod combinations with `/np`."""
    if c is not glob.bot:
        return 'This command can only be used in DM with Aika.'

    if not p.last_np:
        return 'Please /np a map first!'

    # +?<mods> <acc>%?
    if 1 < len(msg) > 2:
        return 'Invalid syntax: !with <mods/acc> ...'

    mods = acc = None

    for param in (p.strip('+%') for p in msg):
        if cmyui._isdecimal(param, _float=True):
            if not 0 <= (acc := float(param)) <= 100:
                return 'Invalid accuracy.'

        elif ~len(param) & 1:  # len(param) % 2 == 0
            mods = Mods.from_str(param)
Example #6
0
@mp_commands.add(Privileges.Normal)
async def mp_ban(p: 'Player', m: 'Match', msg: Sequence[str]) -> str:
    """Ban a pick in the currently loaded mappool."""
    if len(msg) != 1:
        return 'Invalid syntax: !mp ban <pick>'

    if not m.pool:
        return 'No pool currently selected!'

    mods_slot = msg[0]

    # separate mods & slot
    if not (rgx := regexes.mappool_pick.fullmatch(mods_slot)):
        return 'Invalid pick syntax; correct example: "HD2".'

    mods = Mods.from_str(rgx[1])
    slot = int(rgx[2])

    if (mods, slot) not in m.pool.maps:
        return f'Found no {mods_slot} pick in the pool.'

    if (mods, slot) in m.bans:
        return 'That pick is already banned!'

    m.bans.add((mods, slot))
    return f'{mods_slot} banned.'


@mp_commands.add(Privileges.Normal)
async def mp_unban(p: 'Player', m: 'Match', msg: Sequence[str]) -> str:
    """Unban a pick in the currently loaded mappool."""