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
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
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
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
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
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
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
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