Exemple #1
0
def compare(item1, item2):
    """Prints a string comparing the stats of two given items."""
    i1: Item = Item.find_by_name_or_nick(item1)
    i2: Item = Item.find_by_name_or_nick(item2)

    if not i1:
        return f'Error: {item1} does not exist.'
    if not i2:
        return f'Error: {item2} does not exist.'

    out = f':moneybag: __**COMPARE**__ :moneybag:\n'\
          f'**{i1.name.title()} vs {i2.name.title()}:**\n\n'\
          f'**Accuracy**: {i1.accuracy} vs {i2.accuracy} *({i1.accuracy - i2.accuracy})*\n' \
          f'**Damage**: {i1.damage} vs {i2.damage} *({i1.damage - i2.damage})*\n' \
          f'**Armour**: {i1.armour} vs {i2.armour} *({i1.armour - i2.armour})*\n' \
          f'**Prayer Bonus**: {i1.prayer} vs {i2.prayer} *({i1.prayer - i2.prayer})*'
    return out
Exemple #2
0
def eat(author, item):
    if item == 'none' or item == 'nothing':
        author.active_food = None
        author.save()
        return f'You are now eating nothing.'

    try:
        item = Item.find_food_by_name(item)[0]
    except IndexError:
        # No food matching what was sent in
        return f'You cannot eat {item.name}.'
    if item in Item.all_food():
        author.active_food = item
        author.save()
        # TODO: Readd the pluaralization here per this comment
        # return f'You are now eating {items.add_plural(0, itemid)}!'
        return f'You are now eating {item.name}'
    else:
        return f'You cannot eat {item.name}.'
Exemple #3
0
def cook(user: User, food, n=1):
    """Cooks (a given number of) an item."""

    item: Item = Item.find_by_name_or_nick(food)
    if not item:
        return f'Cannot find food called {food} that can be cooked.'

    name = item.name
    cooking_level = user.cook_level
    cooking_req = item.level
    if cooking_level < cooking_req:
        return f'{name} has a cooking requirement ({cooking_req}) higher than your cooking level ({cooking_level}).'

    rr = RecipeRequirement.objects.filter(recipe__creates=item)
    if not rr:
        return "You cannot cook {name}."
    rr = rr[0]
    if user.has_item_amount_by_item(rr.item, rr.amount*n):
        negative_loot = {rr.item: rr.amount*n}
    else:
        return f'You do not have enough items to make {rr.item.pluralize(n)} ' \
               f'({rr.item.pluralize(rr.amount * n)}).'

    burn_chance = calc_burn(user, item)
    num_cooked = 0
    bonus = 0
    if burn_chance == 0:
        num_cooked = n
    else:
        for _ in range(n):
            if random.randint(1, 100) > burn_chance:
                num_cooked += 1
    if cooking_level == 99:
        bonus = random.randint(0, round(n / 20))

    user.update_inventory(negative_loot, remove=True)
    user.update_inventory({item: num_cooked})
    user.update_inventory({BURNT_FOOD: n - num_cooked})
    xp = XP_FACTOR * num_cooked * item.xp
    user.cook_xp += xp
    user.save()
    level_after = user.cook_level

    xp_formatted = '{:,}'.format(xp)
    out = f'After cooking {item.pluralize(n)}, you successfully cook ' \
          f'{num_cooked} and burn {n - num_cooked}! '
    if bonus > 0:
        out += f'Due to your cooking perk, you have also cooked an additional {item.pluralize(n)}! '
    out += 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
Exemple #4
0
def print_item_stats(itemname: str):
    """Prints the stats of an item."""
    item: Item = Item.find_by_name_or_nick(itemname)
    if not item:
        return f'Error: {item} is not an item.'

    name = item.name.title()
    value = '{:,}'.format(item.value)
    aliases = ', '.join(item.alias_strings)

    out = f'__**:moneybag: ITEMS :moneybag:**__\n'
    out += f'**Name**: {name}\n'
    if len(aliases) > 0:
        out += f'**Aliases**: {aliases}\n'
    out += f'**Value**: {value} gp\n'

    if item.slot > 0:
        damage = item.damage if item.damage else 0
        accuracy = item.accuracy if item.accuracy else 0
        prayer = item.prayer if item.prayer else 0
        level = item.level if item.level else 1
        armour = item.armour if item.armour else 0

        out += f'\n**Damage**: {damage}\n'
        out += f'**Accuracy**: {accuracy}\n'
        out += f'**Armour**: {armour}\n'
        out += f'**Prayer Bonus**: {prayer}\n'
        out += f'**Slot**: {SLOTS[str(item.slot)].title()}\n'
        out += f'**Combat Requirement**: {level}\n'
    if item.is_gatherable:
        xp = item.xp
        level = item.level if item.level else 1
        out += f'**Gather Requirement**: {level}\n'
        out += f'**xp**: {xp}\n'

    out += "\n**Drop Sources:**"
    dropping_monsters = item.monsterloot_set.all().order_by('rarity')
    ml: MonsterLoot
    for ml in dropping_monsters:
        if ml.min_amount == ml.max_amount:
            amt = ml.min_amount
        else:
            amt = "%d-%d" % (ml.min_amount, ml.max_amount)

        out += f'\n{ml.monster.name.title()} _(amount: {amt}, rarity: {ml.rarity_str})_'

    out += clue_helpers.print_item_from_lootable(item)
    return out
Exemple #5
0
def craft(user: User, recipe, n=1):
    """Crafts (a given number of) an item."""

    recipeitem: Item = Item.find_by_name_or_nick(recipe)
    if not recipeitem:
        return f'Cannot find item {recipe}.'

    recipe: Recipe = Recipe.objects.filter(creates=recipeitem)
    if not recipe:
        return f'Cannot find recipe that crafts {recipeitem.name}.'
    recipe = recipe[0]

    name = recipeitem.name
    artisan_level = user.artisan_level
    artisan_req = recipe.level_requirement
    if artisan_level < artisan_req:
        return f'Error: {name} has a artisan requirement ({artisan_req}) ' \
               f'higher than your artisan level ({artisan_level}).'

    inputs = recipe.get_requirements()
    negative_loot = {}
    for rr in list(inputs):
        if user.has_item_amount_by_item(rr.item, rr.amount*n):
            negative_loot[rr.item] = rr.amount * n
        else:
            return f'Error: you do not have enough items to make {recipe.creates.pluralize(n)} ' \
                   f'({rr.item.pluralize(rr.amount * n)}).'

    bonus = random.randint(1, math.floor(n/20)) if artisan_level == 99 and n >=20 else 0

    goldsmith_bonus = 1
    if recipe == GOLD_BAR_RECIPE and GOLD_GAUNTLETS in user.equipment_slots:
        goldsmith_bonus = 2

    user.update_inventory(negative_loot, remove=True)
    user.update_inventory({recipe.creates: n + bonus})
    xp = XP_FACTOR * goldsmith_bonus * n * recipe.creates.xp
    user.artisan_xp += xp
    user.save()
    level_after = user.artisan_level

    xp_formatted = '{:,}'.format(xp)
    out = f'Successfully crafted {recipe.creates.pluralize(n)}! 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 {recipe.creates.pluralize(bonus)}! '
    if level_after > artisan_level:
        out += f'You have also gained {level_after - artisan_level} artisan levels!'
    return out
Exemple #6
0
def equip_item(author: User, item: str):
    """Takes an item out of a user's inventory and places it into their equipment."""
    found_item = Item.find_by_name_or_nick(item)
    if found_item is None:
        return f'Error: {item} does not exist.'

    item_level = found_item.level
    user_cb_level = author.combat_level

    # Error checking/verification
    if user_cb_level < item_level:
        return f'Error: Insufficient level to equip item ({found_item.level}). \
                Your current combat level is {user_cb_level}.'

    if not author.has_item_by_item(found_item):
        return f'Error: {found_item.name} not in inventory.'

    if not found_item.is_equippable:
        return f'Error: {item} cannot be equipped.'

    if found_item.is_max_only and not author.is_maxed:
        return f"You cannot equip this item since you do not have {author.max_possible_level} skill total."

    slot = found_item.slot - 1  # I blame coiz for starting this at slot 1 :ANGERY:
    curr_equip = author.equipment_slots[slot]

    # if found_item == curr_equip:
    #     return f"You already have {found_item.name} equipped!"

    item_name = found_item.name
    slot_name = author.equipment_slot_strs[slot]

    # Set the equipment slot
    setattr(author, slot_name, found_item)

    # Update the inventories
    author.update_inventory(curr_equip)
    author.update_inventory(found_item, remove=True)

    author.save()
    return f'{item_name} equipped to {SLOTS[str(slot+1)]}!'
Exemple #7
0
def unequip_item(author: User, item: str):
    """Takes an item out of a user's equipment and places it into their inventory."""
    found_item = Item.find_by_name_or_nick(item)
    if not found_item:
        return f'Error: {item} does not exist.'

    item_name = found_item.name
    equipment = author.all_armour

    if found_item not in author.equipment_slots:
        return f'You do not have {item_name} equipped.'

    slot = found_item.slot - 1
    slot_name = author.equipment_slot_strs[slot]
    curr_equip = author.equipment_slots[slot]

    # Set the equipment slot
    setattr(author, slot_name, None)
    author.update_inventory(curr_equip)
    author.save()
    return f'{found_item.name} unequipped from {SLOTS[str(slot+1)]}!'
Exemple #8
0
def print_pets(person):
    """Prints a formatted list of pets a user has."""

    user_pets = [item.item for item in person.get_pets()]
    all_pets = Item.all_pets()

    pets_header = f':cat: __**PETS**__ :dog:\n'
    messages = []
    out = pets_header
    for pet in all_pets:
        if pet in user_pets:
            out += f"**{pet.name.title()}**\n"
        else:
            out += f'{pet.name.title()}\n'

        if len(out) > 1900:
            messages.append(out)
            out = pets_header

    out += f'{len(user_pets)}/{len(all_pets)}'
    messages.append(out)
    return messages
Exemple #9
0
def print_recipe(user, recipe):
    """Prints details related to a particular recipe."""

    created_item = Item.find_by_name_or_nick(recipe)
    recipe = Recipe.objects.filter(creates=created_item)
    if not recipe:
        return f'Error: cannot find recipe that crafts {recipe}.'
    recipe = recipe[0]

    out = f'{CRAFT_HEADER}'\
          f'**Name**: {created_item.name.title()}\n'\
          f'**Artisan Requirement**: {recipe.level_requirement}\n'\
          f'**XP Per Item**: {created_item.xp}\n'\
          f'**Inputs**:\n'

    item_requirements = RecipeRequirement.objects.filter(recipe=recipe)
    for requirement in item_requirements:
        if user.has_item_by_item(requirement.item):
            out += f'~~{requirement.item.pluralize(requirement.amount)}~~\n'
        else:
            out += f'{requirement.item.pluralize(requirement.amount)}\n'

    return out
Exemple #10
0
def sell(userid, item, number):
    """Sells (a given amount) of an item from a user's inventory."""
    user = User.objects.get(id=userid)
    item: Item = Item.find_by_name_or_nick(item)
    if not item:
        return f'Error: {item} is not an item.'

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

    item_name = item.name
    if user.has_item_amount_by_item(item, number):
        value = item.value
        coin = Item.objects.get(name="coins")
        user.update_inventory(Counter({coin: value*number}))
        user.update_inventory(Counter({item: number}), remove=True)

        value_formatted = '{:,}'.format(value * number)
        return f'{number} {item_name} sold for {value_formatted} coins!'
    else:
        return f'Error: {item_name} not in inventory or you do not have at least {number} in your inventory.'
Exemple #11
0
def bury(author: User, itemname: str, number: int):
    """Buries (a given amount) of an item and gives the user prayer xp."""

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

    if not item.is_buryable:
        return f"You cannot bury {item.name}."

    user_items = author.get_item_by_item(item)
    if not author.has_item_amount_by_item(item, number) or not user_items:
        # TODO: Pluralize this
        return f'You do not have enough {item.name} in your inventory.'

    user_item: UserInventory = user_items[0]
    xp_difference = item.xp * number
    pre_bury_level = author.prayer_level

    author.prayer_xp += xp_difference
    author.save()

    if user_item.amount == number:
        user_item.delete()
    else:
        user_item.amount -= number
        user_item.save()

    post_bury_level = author.prayer_level
    level_difference = post_bury_level - pre_bury_level
    prayer_xp_formatted = '{:,}'.format(xp_difference)

    out = PRAYER_HEADER
    out += f'You get {prayer_xp_formatted} prayer xp from your {item.pluralize(number)}! '
    if level_difference:
        out += f'You have also gained {level_difference} prayer levels!'
    return out
Exemple #12
0
def buy(userid, item, number):
    """Buys (a given amount) of an item and places it in the user's inventory."""
    user = User.objects.get(id=userid)
    item: Item = Item.find_by_name_or_nick(item)
    if not item:
        return f'Error: {item} is not an item.'

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

    item_name = item.name

    if item_in_shop(item.id):
        items = open_shop()
        quest_id = int(items[str(item.id)])
        quest_req = None
        if quest_id:
            quest_req = Quest.objects.get(id=quest_id)

        if not quest_id or user.has_completed_quest(quest_req):
            value = item.value
            cost = 4 * number * value
            coin = Item.objects.get(name="coins")
            if user.has_item_amount_by_item(coin, cost):
                user.update_inventory(Counter({coin: cost}), remove=True)
                user.update_inventory(Counter({item: number}))
                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 available in shop.'
Exemple #13
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
Exemple #14
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