Esempio n. 1
0
def get_result(person, *args):
    """Determines the success and loot of a slayer task."""
    try:
        monsterid, monster_name, num_to_kill, chance = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    out = ''
    if adv.is_success(calc_chance(person.id, monsterid)):
        loot = mon.get_loot(monsterid, int(num_to_kill))
        users.update_inventory(person.id, loot)
        out += print_loot(loot, person, monster_name, num_to_kill)

        xp_gained = mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill)
        users.update_user(person.id, xp_gained, users.SLAYER_XP_KEY)
        users.update_user(person.id, round(0.7 * xp_gained), users.COMBAT_XP_KEY)

        slayer_xp_formatted = '{:,}'.format(xp_gained)
        combat_xp_formatted = '{:,}'.format(round(0.7 * xp_gained))
        out += f'\nYou have also gained {slayer_xp_formatted} slayer xp and {combat_xp_formatted} combat xp.'
    else:
        xp_gained = round(mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill) / 4)
        users.update_user(person.id, xp_gained, users.SLAYER_XP_KEY)
        users.update_user(person.id, round(0.7 * xp_gained), users.COMBAT_XP_KEY)
        slayer_xp_formatted = '{:,}'.format(xp_gained)
        combat_xp_formatted = '{:,}'.format(round(0.7 * xp_gained))
        out += f'{person.mention}, your slayer task of {num_to_kill} {mon.add_plural(monsterid)} has failed.\n'\
               f'You have received {slayer_xp_formatted} slayer xp and {combat_xp_formatted} combat xp.'
    return out
Esempio n. 2
0
def start_quest(userid, questid):
    """Assigns a user a slayer task provided they are not in the middle of another adventure."""
    out = QUEST_HEADER
    if not adv.is_on_adventure(userid):
        try:
            name = get_attr(questid)
        except KeyError:
            return f"Error: 1uest number {questid} does not refer to any quest."
        if has_quest_reqs(userid, questid):
            if int(questid) not in set(users.get_completed_quests(userid)):
                if has_item_reqs(userid, questid):
                    required_items = get_attr(questid, key=ITEM_REQ_KEY)
                    loot = []
                    for item in required_items:
                        loot.extend(required_items[item] * [item])
                    users.update_inventory(userid, loot, remove=True)
                    chance = calc_chance(userid, questid)
                    quest_length = calc_length(userid, questid)
                    quest = adv.format_line(2, userid, adv.get_finish_time(quest_length), questid, chance)
                    adv.write(quest)
                    out += print_quest(questid, quest_length, chance)
                else:
                    return "Error: you do not have all the required items to start this quest."
            else:
                return "Error: you have already done this quest."
        else:
            return "Error: you have not completed the required quests to do this quest."
    else:
        out = adv.print_adventure(userid)
        out += adv.print_on_adventure_error('quest')
    return out
    async def cancel(self, ctx):
        """Cancels your current action."""
        try:
            task = adv.get_adventure(ctx.author.id)

            adventureid = task[0]
            if adventureid == '0':
                if users.item_in_inventory(ctx.author.id, '291', '1'):
                    users.update_inventory(ctx.author.id, ['291'], remove=True)
                    adv.remove(ctx.author.id)
                    out = 'Slayer task cancelled!'
                else:
                    out = 'Error: You do not have a reaper token.'
            elif adventureid == '1':
                adv.remove(ctx.author.id)
                out = 'Killing session cancelled!'
            elif adventureid == '2':
                adv.remove(ctx.author.id)
                out = 'Quest cancelled!'
            elif adventureid == '3':
                adv.remove(ctx.author.id)
                out = 'Gather cancelled!'
            else:
                out = f'Error: Invalid Adventure ID {adventureid}'

        except NameError:
            out = 'You are not currently doing anything.'
        await ctx.send(out)
Esempio n. 4
0
def get_kill_result(person, *args):
    """Determines the loot of a monster grind."""
    try:
        monsterid, monster_name, num_to_kill, length = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    out = ''
    users.add_counter(person.id, monsterid, num_to_kill)
    if mon.get_attr(monsterid, key=mon.SLAYER_KEY):
        factor = 0.75
    else:
        factor = 1

    factor *= items.get_luck_factor(person.id)
    loot = mon.get_loot(monsterid, int(num_to_kill), factor=factor)
    users.update_inventory(person.id, loot)
    out += print_loot(loot, person, monster_name, num_to_kill)

    xp_gained = mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill)
    cb_level_before = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))
    users.update_user(person.id, xp_gained, users.COMBAT_XP_KEY)
    cb_level_after = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))

    combat_xp_formatted = '{:,}'.format(xp_gained)
    out += f'\nYou have also gained {combat_xp_formatted} combat xp'
    if cb_level_after > cb_level_before:
        out += f' and {cb_level_after - cb_level_before} combat levels'
    out += '.'
    users.remove_potion(person.id)

    return out
Esempio n. 5
0
def craft(userid, recipe, n=1):
    """Crafts (a given number of) an item."""
    try:
        recipeid = find_by_name(recipe)
    except KeyError:
        return f'Error: cannot find recipe that crafts {recipe}.'

    name = items.get_attr(recipeid)
    artisan_level = users.xp_to_level(users.read_user(userid, key=users.ARTISAN_XP_KEY))
    artisan_req = get_attr(recipeid, key=LEVEL_REQ_KEY)
    if artisan_level < artisan_req:
        return f'Error: {name} has a gathering requirement ({artisan_req}) ' \
               f'higher than your artisan level ({artisan_level}).'

    inputs = get_attr(recipeid)
    loot = []
    for itemid in list(inputs.keys()):
        if users.item_in_inventory(userid, itemid, number=n * inputs[itemid]):
            loot.extend((n * inputs[itemid]) * [itemid])
        else:
            return f'Error: you do not have enough items to make {n} {items.add_plural(recipeid)} ' \
                   f'({n * inputs[itemid]} {items.add_plural(itemid)}).'

    users.update_inventory(userid, loot, remove=True)
    users.update_inventory(userid, n * [recipeid])
    xp = n * items.get_attr(recipeid, key=items.XP_KEY)
    users.update_user(userid, xp, key=users.ARTISAN_XP_KEY)

    xp_formatted = '{:,}'.format(xp)
    return f'Successfully crafted {n} {items.add_plural(recipeid)}! You have also gained {xp_formatted} artisan xp!'
Esempio n. 6
0
def buy(userid, item, number):
    """Buys (a given amount) of an item and places it in the user's inventory."""
    try:
        itemid = find_by_name(item)
        number = int(number)
    except KeyError:
        return f'Error: {item} is not an item.'
    except ValueError:
        return f'Error: {number} is not a number.'
    item_name = get_attr(itemid)
    if item_in_shop(itemid):
        items = open_shop()
        if int(items[itemid]) in users.get_completed_quests(userid) or int(
                items[itemid]) == 0:
            value = get_attr(itemid, key=VALUE_KEY)
            cost = 4 * number * value
            if users.item_in_inventory(userid, "0", cost):
                users.update_inventory(userid, [itemid] * number)
                users.update_inventory(userid, (4 * number * value) * ["0"],
                                       remove=True)
                value_formatted = '{:,}'.format(4 * value * number)
                return f'{number} {item_name} bought for {value_formatted} coins!'
            else:
                return f'You do not have enough coins to buy this item. ({cost} coins)'
        else:
            return 'Error: You do not have the requirements to buy this item.'
    else:
        return f'Error: {item_name} not in inventory or you do not have at least {number} in your inventory.'
Esempio n. 7
0
def claim(userid, itemname, number):
    try:
        itemid = find_by_name(itemname)
    except KeyError:
        return f"Error: {itemname} is not an item."

    if not users.item_in_inventory(userid, itemid, number):
        return f'You do not have {add_plural(number, itemid)} in your inventory.'

    out = '__**CLAIM**__ :moneybag:\n'

    if int(itemid) == 402:
        out += 'You have received:\n'
        gems = {25: 4, 26: 16, 27: 64, 28: 128, 463: 1024, 465: 2048}
        loot = []
        for _ in range(number):
            while True:
                gem_type = random.choice(gems.keys(), 1)[0]
                if random.randint(1, gems[gem_type]) == 1:
                    loot.append(gem_type)
                    break
        users.update_inventory(userid, loot)
        loot_counter = Counter(loot)
        for gemid in loot_counter.keys():
            out += f'{add_plural(loot_counter[gemid], gemid)}\n'
        out += f'from your {add_plural(number, itemid)}.'
        users.update_inventory(userid, number * [itemid], remove=True)
    else:
        out += f'{get_attr(itemid)} is not claimable.'
    return out
Esempio n. 8
0
def get_reaper_result(person, *args):
    """Determines the success and loot of a reaper task."""
    try:
        monsterid, monster_name, num_to_kill, chance = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    out = ''
    users.add_counter(person.id, monsterid, num_to_kill)
    if adv.is_success(calc_chance(person.id, monsterid, num_to_kill)):
        users.remove_potion(person.id)
        factor = 0.7 * items.get_luck_factor(person.id)
        loot = mon.get_loot(monsterid, int(num_to_kill), factor=factor)
        loot['291'] = 1
        users.update_inventory(person.id, loot)
        out += print_loot(loot, person, monster_name, num_to_kill)

        xp_gained = XP_FACTOR * mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill)
        cb_level_before = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))
        slay_level_before = users.xp_to_level(users.read_user(person.id, users.SLAYER_XP_KEY))
        users.update_user(person.id, xp_gained, users.SLAYER_XP_KEY)
        users.update_user(person.id, round(0.7 * xp_gained), users.COMBAT_XP_KEY)
        cb_level_after = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))
        slay_level_after = users.xp_to_level(users.read_user(person.id, users.SLAYER_XP_KEY))

        slayer_xp_formatted = '{:,}'.format(xp_gained)
        combat_xp_formatted = '{:,}'.format(round(0.7 * xp_gained))
        out += f'\nYou have also gained {slayer_xp_formatted} slayer xp and {combat_xp_formatted} combat xp. '
        if cb_level_after > cb_level_before:
            out += f'In addition, you have gained {cb_level_after - cb_level_before} combat levels. '
        if slay_level_after > slay_level_before:
            out += f'Also, as well, you have gained {slay_level_after - slay_level_before} slayer levels. '
    else:

        users.remove_potion(person.id)
        factor = int(chance)/170 * items.get_luck_factor(person.id)
        loot = mon.get_loot(monsterid, int(num_to_kill), factor=factor)
        loot.append('291')
        users.update_inventory(person.id, loot)
        out += print_loot(loot, person, monster_name, num_to_kill)

        xp_gained = round(XP_FACTOR * mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill) * factor)
        cb_level_before = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))
        slay_level_before = users.xp_to_level(users.read_user(person.id, users.SLAYER_XP_KEY))
        users.update_user(person.id, xp_gained, users.SLAYER_XP_KEY)
        users.update_user(person.id, round(0.7 * xp_gained), users.COMBAT_XP_KEY)
        cb_level_after = users.xp_to_level(users.read_user(person.id, users.COMBAT_XP_KEY))
        slay_level_after = users.xp_to_level(users.read_user(person.id, users.SLAYER_XP_KEY))

        slayer_xp_formatted = '{:,}'.format(xp_gained)
        combat_xp_formatted = '{:,}'.format(round(0.7 * xp_gained))
        out += f'\nYou have received lower loot and experience because you have died.'\
               f'\nYou have received {slayer_xp_formatted} slayer xp and {combat_xp_formatted} combat xp. '
        if cb_level_after > cb_level_before:
            out += f'Also, you have gained {cb_level_after - cb_level_before} combat levels. '
        if slay_level_after > slay_level_before:
            out += f'In addition, you have gained {slay_level_after - slay_level_before} slayer levels. '
    return out
 async def starter_gear(self, ctx):
     """Gives the user a set of bronze armour."""
     if ctx.channel.id == SHOP_CHANNEL or ctx.channel.id == COMBAT_CHANNEL:
         if users.read_user(ctx.author.id, key=users.COMBAT_XP_KEY) == 0:
             users.update_inventory(ctx.author.id, [63, 66, 69, 70])
             await ctx.send(
                 f'Bronze set given to {ctx.author.name}! You can see your items by typing `~inventory` '
                 f'and equip them by typing `~me equip [item]`. You can see your current stats by typing '
                 f'`~me`.')
         else:
             await ctx.send(
                 f'You are too experienced to get the starter gear, {ctx.author.name}.'
             )
Esempio n. 10
0
def get_clue_scroll(person, *args):
    try:
        difficulty, length = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    difficulty = int(difficulty)
    loot = get_loot(difficulty)
    users.update_inventory(person.id, loot)
    users.add_counter(person.id, str(difficulty), 1, key=users.CLUES_KEY)
    out = f'{CLUE_HEADER}' \
          f'{person.mention}, you have finished your {DIFFICULTY[int(difficulty)]} clue scroll! ' \
          f'You have received the following items:\n'
    out += print_loot(loot, difficulty)
    return out
Esempio n. 11
0
    async def starter_gear(self, ctx):
        """Gives the user a set of bronze armour."""
        if ctx.channel.id == SHOP_CHANNEL or ctx.channel.id == ADVENTURES_CHANNEL or ctx.channel.id in GENERAL_CHANNELS:
            name = get_display_name(ctx.author)
            if users.read_user(ctx.author.id, key=users.COMBAT_XP_KEY) == 0:
                users.update_inventory(ctx.author.id, [63, 66, 69, 70, 64, 72])

                await ctx.send(
                    f'Bronze set given to {name}! You can see your items by typing `~inventory` in #bank '
                    f'and equip them by typing `~equip [item]`. You can see your current stats by typing '
                    f'`~me`. If you need help with commands, feel free to look at #welcome or ask around!'
                )
            else:
                await ctx.send(
                    f'You are too experienced to get the starter gear, {name}.'
                )
Esempio n. 12
0
def get_gather(person, *args):
    try:
        itemid, item_name, number, length = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    loot = int(number) * [itemid]
    xp = int(number) * items.get_attr(itemid, key=items.XP_KEY)
    users.update_inventory(person.id, loot)
    users.update_user(person.id, xp, key=users.GATHER_XP_KEY)

    xp_formatted = '{:,}'.format(xp)
    out = f'{GATHER_HEADER}' \
          f'{person.mention}, you gathering session has finished! You have gathered ' \
          f'{number} {items.add_plural(itemid)} and have gained {xp_formatted} gathering xp!'
    return out
Esempio n. 13
0
def craft(userid, recipe, n=1):
    """Crafts (a given number of) an item."""
    try:
        recipeid = find_by_name(recipe.lower())
    except KeyError:
        return f'Cannot find recipe that crafts {recipe}.'
    except TypeError:
        return f'Cannot craft {recipe}.'

    name = items.get_attr(recipeid)
    artisan_level = users.get_level(userid, key=users.ARTISAN_XP_KEY)
    artisan_req = get_attr(recipeid, key=ARTISAN_REQ_KEY)
    if artisan_level < artisan_req:
        return f'Error: {name} has a artisan requirement ({artisan_req}) ' \
               f'higher than your artisan level ({artisan_level}).'

    inputs = get_attr(recipeid)
    recipe_input = []
    for itemid in list(inputs.keys()):
        if users.item_in_inventory(userid, itemid, number=n * inputs[itemid]):
            recipe_input.extend((n * inputs[itemid]) * [itemid])
        else:
            return f'Error: you do not have enough items to make {items.add_plural(n, recipeid)} ' \
                   f'({items.add_plural(n * inputs[itemid], itemid)}).'
    bonus = 0
    if artisan_level == 99:
        for _ in range(n):
            if random.randint(1, 20) == 1:
                bonus += 1
    equipment = users.read_user(userid, users.EQUIPMENT_KEY)
    goldsmith_bonus = 2 if equipment['9'] == '494' and recipeid == '59' else 1

    users.update_inventory(userid, recipe_input, remove=True)
    users.update_inventory(userid, (n + bonus) * [recipeid])
    xp = XP_FACTOR * goldsmith_bonus * n * items.get_attr(recipeid,
                                                          key=items.XP_KEY)
    users.update_user(userid, xp, key=users.ARTISAN_XP_KEY)
    level_after = users.xp_to_level(
        users.read_user(userid, users.ARTISAN_XP_KEY))

    xp_formatted = '{:,}'.format(xp)
    out = f'Successfully crafted {items.add_plural(n, recipeid)}! You have also gained {xp_formatted} artisan xp! '
    if bonus > 0:
        out += f'Due to your 99 artisan perk, you have also created an extra {items.add_plural(bonus, recipeid)}! '
    if level_after > artisan_level:
        out += f'You have also gained {level_after - artisan_level} artisan levels!'
    return out
Esempio n. 14
0
def start_clue(userid, difficulty):
    """Starts a clue scroll."""
    out = f'{CLUE_HEADER}'
    if not adv.is_on_adventure(userid):
        scrollid = str(EASY_CLUE_SCROLL_ID + difficulty - 1)
        if not users.item_in_inventory(userid, scrollid):
            return f'Error: you do not have a {DIFFICULTY[difficulty]} clue scroll in your inventory.'
        users.update_inventory(userid, [scrollid], remove=True)

        length = math.floor(calc_length(userid, difficulty) / 60)
        clue = adv.format_line(4, userid, adv.get_finish_time(length * 60),
                               difficulty, length)
        adv.write(clue)
        out += f'You are now doing a {DIFFICULTY[difficulty]} clue scroll for {length} minutes.'
    else:
        out = adv.print_adventure(userid)
        out += adv.print_on_adventure_error('clue scroll')
    return out
Esempio n. 15
0
def sell(userid, item, number):
    """Sells (a given amount) of an item from a user's inventory."""
    try:
        itemid = find_by_name(item)
        number = int(number)
    except KeyError:
        return f'Error: {item} is not an item.'
    except ValueError:
        return f'Error: {number} is not a number.'

    item_name = get_attr(itemid)
    if users.item_in_inventory(userid, itemid, number=number):
        value = get_attr(itemid, key=VALUE_KEY)
        users.update_inventory(userid, [itemid] * number, remove=True)
        ac.update_account(userid, number * value)
        value_formatted = '{:,}'.format(value * number)
        return f'{number} {item_name} sold for G${value_formatted}!'
    else:
        return f'Error: {item_name} not in inventory or you do not have at least {number} in your inventory.'
Esempio n. 16
0
def get_kill_result(person, *args):
    """Determines the loot of a monster grind."""
    try:
        monsterid, monster_name, num_to_kill, length = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    out = ''
    if mon.get_attr(monsterid, key=mon.SLAYER_KEY):
        factor = 0.75
    else:
        factor = 1
    loot = mon.get_loot(monsterid, int(num_to_kill), factor=factor)
    users.update_inventory(person.id, loot)
    out += print_loot(loot, person, monster_name, num_to_kill)
    xp_gained = mon.get_attr(monsterid, key=mon.XP_KEY) * int(num_to_kill)
    users.update_user(person.id, xp_gained, users.COMBAT_XP_KEY)
    combat_xp_formatted = '{:,}'.format(xp_gained)
    out += f'\nYou have also gained {combat_xp_formatted} combat xp.'
    return out
Esempio n. 17
0
def drink(userid, name):
    try:
        itemid = find_by_name(name)
    except KeyError:
        return f'Error: {name} does not exist.'
    item_name = get_attr(itemid)

    is_pot = get_attr(itemid, key=POT_KEY)
    if is_pot:
        if users.item_in_inventory(userid, itemid):
            users.update_inventory(userid, [itemid], remove=True)
            equipment = users.read_user(userid, key=users.EQUIPMENT_KEY)
            equipment['15'] = str(itemid)
            users.update_user(userid, equipment, key=users.EQUIPMENT_KEY)
        else:
            return f"You do not have any {add_plural(0, itemid)} in your inventory."
    else:
        return f"{item_name} isn't a potion!"

    out = f'You drank the {item_name}! Your stats will be increased for your next adventure.'
    return out
Esempio n. 18
0
def get_result(person, *args):
    """Gets the result of a quest."""
    try:
        questid, chance = args[0]
    except ValueError as e:
        print(e)
        raise ValueError

    out = f'{QUEST_HEADER}**{person.mention}, here is the result of your quest, {get_attr(questid)}**:\n'
    if adv.is_success(calc_chance(person.id, questid)):
        out += f'*{get_attr(questid, key=SUCCESS_KEY)}*\n\n'
        reward = get_attr(questid, key=REWARD_KEY)
        out += f'**Reward**:\n'
        loot = []
        for itemid in reward:
            loot.extend(reward[itemid] * [itemid])
            out += f'{reward[itemid]} {items.get_attr(itemid)}\n'
        users.update_inventory(person.id, loot)
        users.update_user(person.id, questid, key=users.QUESTS_KEY)
    else:
        out += f'*{get_attr(questid, key=FAILURE_KEY)}*'
    return out
Esempio n. 19
0
    async def jeopardy(self, ctx, textonly='f'):
        """Gives users GasterCash in exchange for correct answers."""
        if ctx.channel.id == JEOPARDY_CHANNEL:
            question_args = quiz.get_new_question()
            category = question_args[0]
            value = question_args[1]
            question = question_args[2]
            answer = question_args[3]

            if textonly != 't':
                quiz.draw_jeopardy(question)
                await ctx.send(
                    f"*{ctx.author.name}: I'll take {category} for {value} coins, Alex.*",
                    file=discord.File(quiz.OUT_FILE))
            else:
                await ctx.send(
                    f"*{ctx.author.name}: I'll take {category} for {value} coins, Alex.*\n{question}"
                )

            while True:
                message = await self.bot.wait_for('message')
                if message.author == ctx.author:
                    if message.content.lower() in answer.lower() and len(
                            message.content) > 1:
                        amount_formatted = '{:,}'.format(value)

                        out = f"Answer {answer} is correct! "
                        if not users.read_user(ctx.author.id,
                                               key=users.IRONMAN_KEY):
                            users.update_inventory(ctx.author.id,
                                                   value * ['0'])
                            out += f"{ctx.author.name}'s balance has increased by {amount_formatted} coins!"
                        await ctx.send(out)
                        break
                    else:
                        await ctx.send(
                            f"Answer {message.content} is incorrect. Correct answer was {answer}."
                        )
                        break
Esempio n. 20
0
    async def sellall(self, ctx, maxvalue=None):
        """Sells all items in the player's inventory (below a certain value) for GasterCoin."""
        if ctx.channel.id == SHOP_CHANNEL or ctx.channel.id in GENERAL_CHANNELS:

            name = get_display_name(ctx.author)
            if maxvalue is not None:
                value = users.get_value_of_inventory(ctx.author.id,
                                                     under=maxvalue)
                users.update_inventory(ctx.author.id, value * ["0"])
                users.clear_inventory(ctx.author.id, under=maxvalue)
                value_formatted = '{:,}'.format(value)
                maxvalue_formatted = '{:,}'.format(int(maxvalue))
                name = get_display_name(ctx.author)
                out = f"All items in {name}'s inventory worth under {maxvalue_formatted} coins "\
                      f"sold for {value_formatted} coins!"
            else:
                value = users.get_value_of_inventory(ctx.author.id)
                users.update_inventory(ctx.author.id, value * ["0"])
                users.clear_inventory(ctx.author.id)
                value_formatted = '{:,}'.format(value)
                out = f"All items in {name}'s inventory "\
                      f"sold for {value_formatted} coins!"
            await ctx.send(out)
Esempio n. 21
0
def get_gather(person, *args):
    try:
        itemid, item_name, number, length = args[0]
    except ValueError as e:
        print(e)
        raise ValueError
    loot = int(number) * [itemid]
    xp = XP_FACTOR * int(number) * items.get_attr(itemid, key=items.XP_KEY)
    users.update_inventory(person.id, loot)
    gather_level_before = users.xp_to_level(
        users.read_user(person.id, users.GATHER_XP_KEY))
    users.update_user(person.id, xp, key=users.GATHER_XP_KEY)
    gather_level_after = users.xp_to_level(
        users.read_user(person.id, users.GATHER_XP_KEY))

    xp_formatted = '{:,}'.format(xp)
    out = f'{GATHER_HEADER}' \
          f'{person.mention}, your gathering session has finished! You have gathered ' \
          f'{items.add_plural(number, itemid)} and have gained {xp_formatted} gathering xp! '
    if gather_level_after > gather_level_before:
        out += f'In addition, you have gained {gather_level_after - gather_level_before} gathering levels!'
    users.remove_potion(person.id)
    return out
Esempio n. 22
0
def cook(userid, food, n=1):
    """Cooks (a given number of) an item."""
    try:
        foodid = find_by_name(food, cook=True)
    except KeyError:
        return f'Cannot find food called {food} that can be cooked.'
    except TypeError:
        return f'Cannot cook {food}.'

    name = items.get_attr(foodid)
    cooking_level = users.get_level(userid, key=users.COOK_XP_KEY)
    cooking_req = get_attr(foodid, key=COOKING_REQ_KEY)
    if cooking_level < cooking_req:
        return f'{name} has a cooking requirement ({cooking_req}) higher than your cooking level ({cooking_level}).'

    burn_chance = calc_burn(userid, foodid)
    num_cooked = 0
    if burn_chance == 0:
        num_cooked = n
    else:
        for _ in range(n):
            if random.randint(1, 100) > burn_chance:
                num_cooked += 1

    inputs = get_attr(foodid)
    food_input = []
    for itemid in list(inputs.keys()):
        if users.item_in_inventory(userid,
                                   itemid,
                                   number=num_cooked * inputs[itemid]):
            food_input.extend((num_cooked * inputs[itemid]) * [itemid])
        else:
            return f'Error: you do not have enough items to make {items.add_plural(n, foodid)} ' \
                   f'({items.add_plural(n * inputs[itemid], itemid)}).'

    users.update_inventory(userid, food_input, remove=True)
    users.update_inventory(userid, num_cooked * [foodid])
    users.update_inventory(userid, (n - num_cooked) * ['469'])
    xp = XP_FACTOR * num_cooked * items.get_attr(foodid, key=items.XP_KEY)
    users.update_user(userid, xp, key=users.COOK_XP_KEY)
    level_after = users.xp_to_level(users.read_user(userid, users.COOK_XP_KEY))

    xp_formatted = '{:,}'.format(xp)
    out = f'After cooking {items.add_plural(n, foodid)}, you successfully cook ' \
          f'{num_cooked} and burn {n - num_cooked}! ' \
          f'You have also gained {xp_formatted} cooking xp! '
    if level_after > cooking_level:
        out += f'You have also gained {level_after - cooking_level} cooking levels!'
    return out
Esempio n. 23
0
    async def trade(self, ctx, *args):
        """Trades to a person a number of a given object for a given price."""
        if ctx.channel.id == SHOP_CHANNEL or ctx.channel.id in GENERAL_CHANNELS:
            if users.read_user(ctx.author.id, key=users.IRONMAN_KEY):
                await ctx.send('Ironmen cannot trade.')
                return

            if len(args) < 4:
                await ctx.send(
                    'Arguments missing. Syntax is `~trade [name] [number] [item] [offer]`.'
                )
                return

            name = args[0]
            for member in ctx.guild.members:
                if name.lower() in member.name.lower():
                    name_member = member
                    break
            else:
                await ctx.send(f'{name} not found in server.')
                return
            if users.read_user(name_member.id, key=users.IRONMAN_KEY):
                await ctx.send('You cannot trade with an ironman.')
                return

            try:
                number = int(args[1])
            except ValueError:
                await ctx.send(f'{args[1]} is not a valid number.')
                return

            try:
                offer = users.parse_int(args[-1])
                itemid = items.find_by_name(' '.join(args[2:-1]))
            except ValueError:
                await ctx.send(f'{args[-1]} is not a valid offer.')
                return
            except KeyError:
                await ctx.send(f"{' '.join(args[2:-1])} is not a valid item.")
                return

            if not users.item_in_inventory(ctx.author.id, itemid, number):
                await ctx.send(
                    f'You do not have {items.add_plural(number, itemid)} in your inventory.'
                )
                return

            if not items.is_tradable(itemid):
                await ctx.send(
                    f'You can not trade this item. ({items.get_attr(itemid)})')
                return

            if not users.item_in_inventory(name_member.id, "0", offer):
                await ctx.send(
                    f'{get_display_name(name_member)} does not have enough gold to buy this many items.'
                )
                return

            name = get_display_name(ctx.author)
            offer_formatted = '{:,}'.format(offer)
            out = f'{items.SHOP_HEADER}{name.title()} wants to sell {name_member.mention} ' \
                  f'{items.add_plural(number, itemid)} for {offer_formatted} coins. To accept this offer, reply ' \
                  f'to this post with a :thumbsup:. Otherwise, this offer will expire in one minute.'
            msg = await ctx.send(out)
            await msg.add_reaction('\N{THUMBS UP SIGN}')

            while True:
                try:
                    reaction, user = await self.bot.wait_for('reaction_add',
                                                             timeout=60)
                    if str(
                            reaction.emoji
                    ) == '👍' and user == name_member and reaction.message.id == msg.id:
                        price = offer * ["0"]
                        users.update_inventory(name_member.id,
                                               price,
                                               remove=True)
                        users.update_inventory(ctx.author.id, price)
                        loot = number * [itemid]
                        users.update_inventory(ctx.author.id,
                                               loot,
                                               remove=True)
                        users.update_inventory(name_member.id, loot)

                        buyer_name = get_display_name(name_member)
                        await ctx.send(
                            f'{items.SHOP_HEADER}{name.title()} successfully sold '
                            f'{items.add_plural(number, itemid)} to {buyer_name} for '
                            f'{offer_formatted} coins!')
                        return
                except asyncio.TimeoutError:
                    await msg.edit(
                        content=
                        f'One minute has passed and your offer has been cancelled.'
                    )
                    return
Esempio n. 24
0
    async def deathmatch(self, ctx, opponent='rand', bet=None):
        """Allows users to duke it out in a 1v1 match."""
        if ctx.channel.id == DUEL_CHANNEL or ctx.channel.id in GENERAL_CHANNELS:
            author_name = get_display_name(ctx.author)
            if bet is not None:
                if users.read_user(ctx.author.id, key=users.IRONMAN_KEY):
                    await ctx.send('Ironmen cannot start staked deathmatches.')
                    return
                try:
                    bet = users.parse_int(bet)
                except ValueError:
                    await ctx.send(f'{bet} does not represent a valid number.')
                bet_formatted = '{:,}'.format(bet)
                if not users.item_in_inventory(ctx.author.id, '0', bet):
                    await ctx.send(f'You do not have {bet_formatted} coins.')
                    return
                try:
                    opponent_member = parse_name(ctx.message.guild, opponent)
                except NameError:
                    await ctx.send(f'{opponent} not found in server.')
                    return
                except AmbiguousInputError as members:
                    await ctx.send(
                        f'Input {opponent} can refer to multiple people ({members})'
                    )
                    return
                if opponent_member.id == ctx.author.id:
                    await ctx.send('You cannot fight yourself.')
                    return
                if users.read_user(opponent_member.id, key=users.IRONMAN_KEY):
                    await ctx.send(
                        'You cannot start a staked deathmatch with an ironman.'
                    )
                    return
                bet_formatted = '{:,}'.format(bet)
                opponent_name = get_display_name(opponent_member)
                if not users.item_in_inventory(opponent_member.id, '0', bet):
                    await ctx.send(
                        f'{opponent_name} does not have {bet_formatted} coins.'
                    )
                    return
                users.update_inventory(ctx.author.id, bet * ['0'], remove=True)
                out = f'Deathmatch set up between {author_name} and {opponent_member.mention} with bet ' \
                      f'{bet_formatted} coins! To confirm this match, {opponent_name} must react to ' \
                      f'this message with a :thumbsup: in the next minute. If a minute passes or if the ' \
                      f'challenger reacts to this message, the deathmatch will be cancelled and the deposit ' \
                      f'refunded.'
                msg = await ctx.send(out)
                await msg.add_reaction('\N{THUMBS UP SIGN}')

                while True:
                    try:
                        reaction, user = await self.bot.wait_for(
                            'reaction_add', timeout=60)
                        if str(reaction.emoji
                               ) == '👍' and user == opponent_member:
                            users.update_inventory(opponent_member.id,
                                                   bet * ['0'],
                                                   remove=True)
                            deathmatch_messages = dm.do_deathmatch(
                                ctx.author, opponent_member, bet=bet_formatted)
                            for message in deathmatch_messages[:-1]:
                                await msg.edit(content=message)
                                await asyncio.sleep(1)
                            users.update_inventory(deathmatch_messages[-1],
                                                   2 * bet * ['0'])
                            return
                        elif user == ctx.author:
                            users.update_inventory(ctx.author.id, bet * ['0'])
                            await msg.edit(
                                content=
                                f'{author_name} has declined their challenge and '
                                f'the deposit of {bet_formatted} coins has been returned.'
                            )
                            return
                    except asyncio.TimeoutError:
                        users.update_inventory(ctx.author.id, bet * ['0'])
                        await msg.edit(
                            content=
                            f'One minute has passed and the deathmatch has been cancelled. '
                            f'The deposit of {bet_formatted} coins has been returned.'
                        )
                        return
            else:
                try:
                    opponent_member = parse_name(ctx.message.guild, opponent)
                except NameError:
                    await ctx.send(f'{opponent} not found in server.')
                    return
                except AmbiguousInputError as members:
                    await ctx.send(
                        f'Input {opponent} can refer to multiple people ({members})'
                    )
                    return
                msg = await ctx.send(dm.DEATHMATCH_HEADER)
                deathmatch_messages = dm.do_deathmatch(ctx.author,
                                                       opponent_member)
                for message in deathmatch_messages[:-1]:
                    await msg.edit(content=message)
                    await asyncio.sleep(1)