예제 #1
0
def start_quest(guildid, channelid, user: User, questid):
    """Assigns a user a slayer task provided they are not in the middle of another adventure."""
    from miniscape import adventures as adv

    if adv.is_on_adventure(user.id):
        out = adv.print_adventure(user.id)
        out += adv.print_on_adventure_error('quest')
        return out


    try:
        quest = Quest.objects.get(id=questid)
    except ObjectDoesNotExist:
        return f"Error: quest number {questid} does not refer to any quest."

    if quest in user.completed_quests_list:
        return "Error: you have already done this quest."

    if not user.has_quest_req_for_quest(quest):
        return "Error: you have not completed the required quests to do this quest."

    if not user.has_items_for_quest(quest):
        return "Error: you do not have all the required items to start this quest."

    out = QUEST_HEADER

    chance = calc_chance(user, quest)
    quest_length = calc_length(user, quest)
    quest_adv = adv.format_line(2, user.id, adv.get_finish_time(quest_length), guildid,
                                channelid, questid, chance)
    adv.write(quest_adv)
    out += print_quest(quest, quest_length, chance)

    return out
예제 #2
0
 async def status(self, ctx):
     """Says what you are currently doing."""
     if has_post_permission(ctx.guild.id, ctx.channel.id):
         if adv.is_on_adventure(ctx.author.id):
             out = adv.print_adventure(ctx.author.id)
         else:
             out = 'You are not doing anything at the moment.'
         await ctx.send(out)
예제 #3
0
def get_kill(guildid, channelid, userid, monstername, length=-1, number=-1):
    """Lets the user start killing monsters.."""
    out = f'{SLAYER_HEADER}'
    user = User.objects.get(id=userid)
    monster = Monster.find_by_name_or_nick(monstername)

    if not monster:
        return f'Error: {monstername} is not a monster.'

    completed_quests = set(user.completed_quests.all())
    if monster.quest_req and monster.quest_req not in completed_quests:
        return f'Error: you do not have the required quests to kill this monster.'

    try:
        length = int(length)
        number = int(number)
    except ValueError:
        return f'Error: {length} is not a valid length of time.'

    if not adv.is_on_adventure(user.id):
        monster_name = monster.name
        if user.slayer_level < monster.slayer_level_req:
            return f'Error: {monster.name} has a slayer requirement ({monster.slayer_level_req}) higher ' \
                   f'than your slayer level ({user.slayer_level})'
        if number > 1000 and user.slayer_level == 99:
            number = 1000
        if number > 500 and user.slayer_level < 99:
            number = 500
        if length > 180:
            length = 180

        if int(number) < 0:
            number = calc_number(user, monster, (length + 1) * 60) - 1
            if number > 1000 and user.slayer_level == 99:
                number = 1000
            if number > 500 and user.slayer_level < 99:
                number = 500
        elif int(length) < 0:
            length = math.floor(calc_length(user, monster, number)[1] / 60)
        else:
            return 'Error: argument missing (number or kill length).'

        chance = calc_chance(user, monster, number)

        grind = adv.format_line(1, userid, adv.get_finish_time(length * 60),
                                guildid, channelid, monster.id, monster_name,
                                number, length, chance)
        adv.write(grind)
        out += f'You are now killing {monster.pluralize(number, with_zero=True)} for {length} minutes. ' \
               f'You have a {chance}% chance of successfully killing this many monsters without dying.'
    else:
        out = adv.print_adventure(userid)
        out += adv.print_on_adventure_error('kill')
    return out
예제 #4
0
def get_task(guildid, channelid, author: User):
    """Assigns a user a slayer task provided they are not in the middle of another adventure."""
    out = SLAYER_HEADER

    if not adv.is_on_adventure(author.id):
        cb_level = author.combat_level
        slayer_level = author.slayer_level
        completed_quests = set(author.completed_quests.all())
        equipment = author.equipment_slots

        for _ in range(1000):
            monster = mon.get_random(author, wants_boss=False)

            num_to_kill = random.randint(
                LOWEST_NUM_TO_KILL, LOWEST_NUM_TO_KILL + 15 + 3 * slayer_level)
            base_time, task_length = calc_length(author, monster, num_to_kill)
            chance = calc_chance(author, monster, num_to_kill)

            mon_level = monster.level
            if 0.25 <= task_length / base_time <= 2 \
                    and chance >= 20 \
                    and mon_level / cb_level >= 0.8 \
                    and task_length <= 3600 \
                    and (monster.quest_req and monster.quest_req in completed_quests):
                break
            else:
                log_str = f"Failed to give task to user\n" \
                          f"User: {author.name}, Monster: {monster.name}\n" \
                          f"Conditionals: \n" \
                          f"  task_length / base_time: {task_length / base_time}\n" \
                          f"  chance: {chance}\n"\
                          f"  mon levl / cb lvl: {mon_level / cb_level}\n" \
                          f"  quest req satisfied: {monster.quest_req and monster.quest_req in completed_quests}\n"
                logging.getLogger(__name__).info(log_str)
                continue  # For breakpoints :^)
        else:
            return "Error: gear too low to fight any monsters. Please equip some better gear and try again. " \
                   "If you are new, type `~starter` to get a bronze kit."
        cb_perk = False
        if author.combat_level == 99 and random.randint(1, 20) == 1:
            task_length *= 0.7
            cb_perk = True

        task = adv.format_line(0, author.id, adv.get_finish_time(task_length),
                               guildid, channelid, monster.id, monster.name,
                               num_to_kill, chance)
        adv.write(task)
        out += print_task(author.id)
        if cb_perk is True:
            out += 'Your time has been reduced by 30% due to your combat perk!'
    else:
        out = adv.print_adventure(author.id)
        out += adv.print_on_adventure_error('task')
    return out
예제 #5
0
def get_reaper_task(guildid, channelid, userid):
    """Assigns a user a reaper task provided they are not in the middle of another adventure."""
    out = SLAYER_HEADER
    user: User = User.objects.get(id=userid)
    if user.slayer_level < 50:
        out += "Your slayer level is too low to start a reaper task. You need at least 50 slayer."
        return out
    if user.is_reaper_complete:
        out += 'You have already done a reaper task today. Please come back tomorrow for another one.'
        return out

    if not adv.is_on_adventure(userid):
        completed_quests = set(user.completed_quests.all())
        slayer_level = user.slayer_level
        for _ in range(1000):
            monster = mon.get_random(user, wants_boss=True)
            num_to_kill = random.randint(
                LOWEST_NUM_TO_KILL, LOWEST_NUM_TO_KILL + 15 + 3 * slayer_level)
            base_time, task_length = calc_length(user, monster, num_to_kill)
            chance = calc_chance(user, monster, num_to_kill)
            # print(f'{monsterid} {task_length/base_time} {chance}')
            if 0.25 <= task_length / base_time <= 2 and chance >= 80 \
                    and (monster.quest_req and monster.quest_req in completed_quests):
                break
        else:
            return "Error: gear too low to fight any monsters. Please equip some better gear and try again. " \
                   "If you are new, type `~starter` to get a bronze kit."

        cb_perk = False
        if user.combat_level == 99 and random.randint(1, 20) == 1:
            task_length *= 0.7
            cb_perk = True

        task_length = 0
        task = adv.format_line(5, userid, adv.get_finish_time(task_length),
                               guildid, channelid, monster.id, monster.name,
                               num_to_kill, chance)
        adv.write(task)
        out += print_task(userid, reaper=True)
        if cb_perk:
            out += 'Your time has been reduced by 30% due to your combat perk!'
    else:
        out = adv.print_adventure(userid)
        out += adv.print_on_adventure_error('reaper task')
    return out
예제 #6
0
def set_prayer(userid, prayer):
    """Sets a user's prayer."""
    from miniscape import adventures as adv
    user = User.objects.get(id=userid)

    if adv.is_on_adventure(userid):
        return 'You cannot change your prayer while on an adventure.'

    prayer = Prayer.find_by_name_or_nick(prayer)
    if not prayer:
        return f'{prayer} is not a prayer.'

    if not user.can_use_prayer(prayer):
        return f'You cannot use this prayer.'

    user.prayer_slot = prayer
    user.save()
    out = f'{PRAYER_HEADER}Your prayer has been set to {prayer.name.title()}!'
    return out
예제 #7
0
def start_clue(guildid, channelid, userid, difficulty):
    """Starts a clue scroll."""
    from miniscape import adventures as adv

    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),
                               guildid, channelid, 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
예제 #8
0
def start_clue(guildid, channelid, userid, difficulty):
    """Starts a clue scroll."""
    user = User.objects.get(id=userid)
    out = f'{CLUE_HEADER}'
    if not adv.is_on_adventure(userid):
        scrollid = str(EASY_CLUE_SCROLL_ID + difficulty - 1)
        scroll = Item.objects.get(id=scrollid)
        if not user.has_item_by_item(scroll):
            return f'Error: you do not have a {scroll.name} in your inventory.'
        user.update_inventory(Counter({scroll: 1}), remove=True)

        length = math.floor(calc_length(userid, difficulty) / 60)
        clue = adv.format_line(4, userid, adv.get_finish_time(length * 60),
                               guildid, channelid, 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')
    user.save()
    return out
예제 #9
0
def start_runecraft(guildid, channelid, user: User, item, number=1, pure=0):
    """Starts a runecrafting session."""
    from miniscape import adventures as adv

    out = ''
    if not adv.is_on_adventure(user.id):
        item: Item = Item.find_by_name_or_nick(item)
        if not item:
            return f'{item} is not an item.'

        try:
            number = int(number)
        except ValueError:
            return f'{number} is not a valid number.'

        if not item.is_rune:
            return f'{items.get_attr(itemid)} is not a rune that can be crafted.'

        # Find out if user has the talisman
        rune_type = item.name.split(" ")[0]
        if not user.has_item_by_name(rune_type + " talisman"):
            return f'{items.get_attr(talismanid)} not found in inventory.'

        item_name = item.name
        runecrafting_level = user.rc_level
        runecraft_req = item.level
        player_potion = user.potion_slot.id if user.potion_slot else '0'

        if player_potion == 435:
            boosted_level = runecrafting_level + 3
        elif player_potion == 436:
            boosted_level = runecrafting_level + 6
        else:
            boosted_level = runecrafting_level

        if boosted_level < runecraft_req:
            return f'Error: {item_name} has a runecrafting requirement ({runecraft_req}) higher ' \
                   f'than your runecrafting level ({runecrafting_level})'

        if item.quest_req and not user.has_completed_quest(item.quest_req):
            return f'You do not have the required quest to craft this rune.'
        if not user.has_completed_quest(RUNE_MYSTERIES):
            return f'You do not know how to craft runes.'

        factor = 1 if user.has_completed_quest(ABYSS_QUEST) else 2
        bonus = 0
        for pouch in POUCHES:
            if user.has_item_by_item(pouch):
                bonus += pouch.pouch

        length = factor * math.ceil(number * 1.2 / (28.0 + bonus))
        ess_to_check = PURE_ESSENCE if pure else RUNE_ESSENCE
        if not user.has_item_amount_by_item(ess_to_check, number):
            return f'You do not have enough essence to craft this many runes.'

        rc_session = adv.format_line(6, user.id, adv.get_finish_time(length * 60), guildid, channelid,
                                     item.id, item_name, number, length, pure)
        adv.write(rc_session)
        out += f'You are now crafting {item.pluralize(number)} for {length} minutes.'
    else:
        out = adv.print_adventure(user.id)
        out += adv.print_on_adventure_error('runecrafting session')
    return out
예제 #10
0
def start_gather(guildid, channelid, user: User, itemname, length=-1, number=-1):
    """Starts a gathering session."""
    from miniscape import adventures as adv

    out = ''
    userid = user.id
    if not adv.is_on_adventure(userid):

        item: Item = Item.find_by_name_or_nick(itemname)
        if not item:
            return f'Error: {item} is not an item.'

        try:
            length = int(length)
            number = int(number)
        except ValueError:
            return f'Error: {length} is not a valid length of time.'

        if not item.is_gatherable:
            return f'Error: you cannot gather item {ite.name}.'

        quest_req = item.quest_req
        if quest_req and quest_req not in user.completed_quests_list:
            return f'Error: You do not have the required quest to gather this item.'

        item_name = item.name
        gather_level = user.gather_level
        gather_requirement = item.level
        player_potion = user.potion_slot.id if user.potion_slot else '0'

        if player_potion == 435:
            boosted_level = gather_level + 3
        elif player_potion == 436:
            boosted_level = gather_level + 6
        else:
            boosted_level = gather_level

        if boosted_level < gather_requirement:
            return f'Error: {item_name} has a gathering requirement ({gather_requirement}) higher ' \
                   f'than your gathering level ({gather_level})'

        # Adjust the number approppriately
        if number > 1000 and gather_level == 99:
            number = 1000
        if number > 500 and gather_level < 99:
            number = 500
        if length > 180:
            length = 180

        if int(number) < 0:
            number = calc_number(user,item, length * 60)
            if number > 500:
                number = 500
        elif int(length) < 0:
            length = math.floor(calc_length(user, item, number)[1] / 60)
        else:
            return 'Error: argument missing (number or kill length).'
        gather = adv.format_line(3, userid, adv.get_finish_time(length * 60), guildid, channelid,
                                 item.id, item_name, number, length)
        adv.write(gather)
        out += f'You are now gathering {item.pluralize(number)} for {length} minutes.'
    else:
        out = adv.print_adventure(userid)
        out += adv.print_on_adventure_error('gathering')
    return out