예제 #1
0
    def randomize(self):
        if not hasattr(self, "randomize_attributes"):
            return

        for attribute in sorted(self.randomize_attributes):
            if isinstance(self.randomize_attributes[attribute], type):
                tob = self.randomize_attributes[attribute]
                candidates = [t for t in tob.every if t.rank >= 0]
                setattr(self, attribute, random.choice(candidates).index)
            else:
                minimum, maximum = self.randomize_attributes[attribute]
                setattr(self, attribute, random.randint(minimum, maximum))
예제 #2
0
    async def _open(self, ctx, rarity: str.lower = "common"):
        _("""`[rarity]` - the crate's rarity to open, can be common, uncommon, rare, magic or legendary; defaults to common

            Open one of your crates to receive a weapon. To check which crates contain which items, check `{prefix}help crates`.
            This command takes up a lot of space, so choose a spammy channel to open crates."""
          )
        if rarity not in ["common", "uncommon", "rare", "magic", "legendary"]:
            return await ctx.send(
                _("{rarity} is not a valid rarity.").format(rarity=rarity))
        if ctx.character_data[f"crates_{rarity}"] < 1:
            return await ctx.send(
                _("Seems like you don't have any crate of this rarity yet. Vote me up"
                  " to get a random one or find them!"))
        # A number to detemine the crate item range
        rand = random.randint(0, 9)
        if rarity == "common":
            if rand < 2:  # 20% 20-30
                minstat, maxstat = (20, 30)
            elif rand < 5:  # 30% 10-19
                minstat, maxstat = (10, 19)
            else:  # 50% 1-9
                minstat, maxstat = (1, 9)
        elif rarity == "uncommon":
            if rand < 2:  # 20% 30-35
                minstat, maxstat = (30, 35)
            elif rand < 5:  # 30% 20-29
                minstat, maxstat = (20, 29)
            else:  # 50% 10-19
                minstat, maxstat = (10, 19)
        elif rarity == "rare":
            if rand < 2:  # 20% 35-40
                minstat, maxstat = (35, 40)
            elif rand < 5:  # 30% 30-34
                minstat, maxstat = (30, 34)
            else:  # 50% 20-29
                minstat, maxstat = (20, 29)
        elif rarity == "magic":
            if rand < 2:  # 20% 41-45
                minstat, maxstat = (41, 45)
            elif rand < 5:  # 30% 35-40
                minstat, maxstat = (35, 40)
            else:
                minstat, maxstat = (30, 34)
        elif rarity == "legendary":  # no else because why
            if rand < 2:  # 20% 49-50
                minstat, maxstat = (49, 50)
            elif rand < 5:  # 30% 46-48
                minstat, maxstat = (46, 48)
            else:  # 50% 41-45
                minstat, maxstat = (41, 45)

        item = await self.bot.create_random_item(minstat=minstat,
                                                 maxstat=maxstat,
                                                 minvalue=1,
                                                 maxvalue=250,
                                                 owner=ctx.author)
        await self.bot.pool.execute(
            f'UPDATE profile SET "crates_{rarity}"="crates_{rarity}"-1 WHERE'
            ' "user"=$1;',
            ctx.author.id,
        )
        embed = discord.Embed(
            title=_("You gained an item!"),
            description=_("You found a new item when opening a crate!"),
            color=0xFF0000,
        )
        embed.set_thumbnail(url=ctx.author.avatar_url)
        embed.add_field(name=_("ID"), value=item["id"], inline=False)
        embed.add_field(name=_("Name"), value=item["name"], inline=False)
        embed.add_field(name=_("Type"), value=item["type"], inline=False)
        embed.add_field(name=_("Damage"), value=item["damage"], inline=True)
        embed.add_field(name=_("Armor"), value=item["armor"], inline=True)
        embed.add_field(name=_("Value"),
                        value=f"${item['value']}",
                        inline=False)
        embed.set_footer(text=_("Remaining {rarity} crates: {crates}").format(
            crates=ctx.character_data[f"crates_{rarity}"] - 1, rarity=rarity))
        await self.bot.log_transaction(
            ctx,
            from_=1,
            to=ctx.author.id,
            subject="item",
            data={
                "Name": item["name"],
                "Value": item["value"]
            },
        )
        await ctx.send(embed=embed)
        if rarity == "legendary":
            await self.bot.public_log(
                f"**{ctx.author}** opened a legendary crate and received {item['name']}"
                f" with **{item['damage'] or item['armor']}"
                f" {'damage' if item['damage'] else 'armor'}**.")
        elif rarity == "magic":
            if item["damage"] >= 41:
                await self.bot.public_log(
                    f"**{ctx.author}** opened a magic crate and received {item['name']}"
                    f" with **{item['damage']} damage**.")
            elif item["armor"] >= 41:
                await self.bot.public_log(
                    f"**{ctx.author}** opened a magic crate and received {item['name']}"
                    f" with **{item['armor']} armor**.")
예제 #3
0
            participants = participants[: -(len(participants) - toremove)]
        else:
            await ctx.send(
                _("Tournament started with **{num}** entries.").format(num=toremove)
            )
        text = _("vs")
        while len(participants) > 1:
            participants = random.shuffle(participants)
            matches = list(chunks(participants, 2))

            for match in matches:
                await ctx.send(f"{match[0].mention} {text} {match[1].mention}")
                await asyncio.sleep(2)
                val1 = sum(
                    await self.bot.get_damage_armor_for(match[0])
                ) + random.randint(1, 7)
                val2 = sum(
                    await self.bot.get_damage_armor_for(match[1])
                ) + random.randint(1, 7)
                if val1 > val2:
                    winner = match[0]
                    looser = match[1]
                elif val2 > val1:
                    winner = match[1]
                    looser = match[0]
                else:
                    winner = random.choice(match)
                    looser = match[1 - match.index(winner)]
                participants.remove(looser)
                await ctx.send(
                    _("Winner of this match is {winner}!").format(winner=winner.mention)
예제 #4
0
 async def makeluck(self, ctx):
     """Sets the luck for all gods to a random value and give bonus luck to the top 25 followers."""
     text_collection = ["**This week's luck has been decided:**\n"]
     all_ids = []
     async with self.bot.pool.acquire() as conn:
         for god in self.bot.config.gods:
             luck = (
                 random.randint(
                     god["boundary_low"] * 100, god["boundary_high"] * 100
                 )
                 / 100
             )
             ids = await conn.fetch(
                 'UPDATE profile SET "luck"=round($1, 2) WHERE "god"=$2 RETURNING'
                 ' "user";',
                 luck,
                 god["name"],
             )
             all_ids.extend([u["user"] for u in ids])
             top_followers = [
                 u["user"]
                 for u in await conn.fetch(
                     'SELECT "user" FROM profile WHERE "god"=$1 ORDER BY "favor"'
                     " DESC LIMIT 25;",
                     god["name"],
                 )
             ]
             await conn.execute(
                 'UPDATE profile SET "luck"=CASE WHEN "luck"+round($1, 2)>=2.0 THEN'
                 ' 2.0 ELSE "luck"+round($1, 2) END WHERE "user"=ANY($2);',
                 0.5,
                 top_followers[:5],
             )
             await conn.execute(
                 'UPDATE profile SET "luck"=CASE WHEN "luck"+round($1, 2)>=2.0 THEN'
                 ' 2.0 ELSE "luck"+round($1, 2) END WHERE "user"=ANY($2);',
                 0.4,
                 top_followers[5:10],
             )
             await conn.execute(
                 'UPDATE profile SET "luck"=CASE WHEN "luck"+round($1, 2)>=2.0 THEN'
                 ' 2.0 ELSE "luck"+round($1, 2) END WHERE "user"=ANY($2);',
                 0.3,
                 top_followers[10:15],
             )
             await conn.execute(
                 'UPDATE profile SET "luck"=CASE WHEN "luck"+round($1, 2)>=2.0 THEN'
                 ' 2.0 ELSE "luck"+round($1, 2) END WHERE "user"=ANY($2);',
                 0.2,
                 top_followers[15:20],
             )
             await conn.execute(
                 'UPDATE profile SET "luck"=CASE WHEN "luck"+round($1, 2)>=2.0 THEN'
                 ' 2.0 ELSE "luck"+round($1, 2) END WHERE "user"=ANY($2);',
                 0.1,
                 top_followers[20:25],
             )
             text_collection.append(f"{god['name']} set to {luck}.")
         await conn.execute('UPDATE profile SET "favor"=0 WHERE "god" IS NOT NULL;')
         text_collection.append("Godless set to 1.0")
         ids = await conn.fetch(
             'UPDATE profile SET "luck"=1.0 WHERE "god" IS NULL RETURNING "user";'
         )
         all_ids.extend([u["user"] for u in ids])
     await self.bot.cache.wipe_profile(*all_ids)
     msg = await ctx.send("\n".join(text_collection))
     try:
         await msg.publish()
     except (discord.Forbidden, discord.HTTPException) as e:
         await ctx.send(f"Could not publish the message for some reason: `{e}`")
예제 #5
0
 def attack_probability(self):
     """Calculate a probability of a soldier attack"""
     return 0.5 * (1 + self.health / 100) * random.randint(
         50 + self.experience, 101) / 100
예제 #6
0
    async def yummy(self, ctx):
        _("""Open a trick or treat bag, you can get some with `{prefix}trickortreat`.

            Trick or treat bags contain halloween-themed items, ranging from 1 to 50 base stat.
            Their value will be between 1 and 200.""")
        # better name?
        if ctx.character_data["trickortreat"] < 1:
            return await ctx.send(
                _("Seems you haven't got a trick or treat bag yet. Go get some!"
                  ))
        mytry = random.randint(1, 100)
        if mytry == 1:
            minstat, maxstat = 42, 50
        elif mytry < 10:
            minstat, maxstat = 30, 41
        elif mytry < 30:
            minstat, maxstat = 20, 29
        elif mytry < 50:
            minstat, maxstat = 10, 19
        else:
            minstat, maxstat = 1, 9
        item = await self.bot.create_random_item(
            minstat=minstat,
            maxstat=maxstat,
            minvalue=1,
            maxvalue=200,
            owner=ctx.author,
            insert=False,
        )
        name = random.choice([
            "Jack's",
            "Spooky",
            "Ghostly",
            "Skeletal",
            "Glowing",
            "Moonlight",
            "Adrian's really awesome",
            "Ghost Buster's",
            "Ghoulish",
            "Vampiric",
            "Living",
            "Undead",
            "Glooming",
        ])
        item["name"] = f"{name} {item['type_']}"
        async with self.bot.pool.acquire() as conn:
            await self.bot.create_item(**item, conn=conn)
            await conn.execute(
                'UPDATE profile SET "trickortreat"="trickortreat"-1 WHERE "user"=$1;',
                ctx.author.id,
            )
        await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                     trickortreat=-1)
        embed = discord.Embed(
            title=_("You gained an item!"),
            description=_(
                "You found a new item when opening a trick-or-treat bag!"),
            color=self.bot.config.game.primary_colour,
        )
        embed.set_thumbnail(url=ctx.author.avatar_url)
        embed.add_field(name=_("Name"), value=item["name"], inline=False)
        embed.add_field(name=_("Type"), value=item["type_"], inline=False)
        embed.add_field(name=_("Damage"), value=item["damage"], inline=True)
        embed.add_field(name=_("Armor"), value=item["armor"], inline=True)
        embed.add_field(name=_("Value"),
                        value=f"${item['value']}",
                        inline=False)
        embed.set_footer(
            text=_("Remaining trick-or-treat bags: {bags}").format(
                bags=ctx.character_data["trickortreat"] - 1))
        await ctx.send(embed=embed)
예제 #7
0
파일: __init__.py 프로젝트: indij/IdleRPG
              - If the dice lands on 4, you will receive $900
              - If the dice lands on any other number, you will lose $100

            (This command has a cooldown of 5 seconds.)"""
        )
        if tip > maximum:
            return await ctx.send(
                _("Invalid Tip. Must be in the Range of `1` to `{maximum}`.").format(
                    maximum=maximum
                )
            )
        if money * (maximum - 1) > 100_000:
            return await ctx.send(_("Spend it in a better way. C'mon!"))
        if ctx.character_data["money"] < money:
            return await ctx.send(_("You're too poor."))
        randomn = random.randint(0, maximum)
        if randomn == tip:
            if money > 0:
                async with self.bot.pool.acquire() as conn:
                    await conn.execute(
                        'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                        money * (maximum - 1),
                        ctx.author.id,
                    )
                    await self.bot.log_transaction(
                        ctx,
                        from_=1,
                        to=ctx.author.id,
                        subject="gambling",
                        data={"Amount": money * (maximum - 1)},
                        conn=conn,
예제 #8
0
    async def child(self, ctx):
        _(
            # xgettext: no-python-format
            """Have a child with your partner.

            Children on their own don't do much, but `{prefix}familyevent` can effect your money and crates.
            To have a child, your partner has to be on the server to accept the checkbox.

            There is a 50% chance that you will have a child, and a 50% chance to just *have fun* (if you know what I'm saying) and gain between 10 and 50 lovescore.
            When you have a child, there is a 50% chance for it to be a boy and a 50% chance to be a girl.

            Your partner and you can enter a name for your child once the bot prompts you to. (Do not include `{prefix}`)
            If you fail to choose a name in time, the bot will choose one for you from about 500 pre-picked ones.

            For identification purposes, you cannot have two children with the same name in your family, so make sure to pick a unique one.

            Only players who are married can use this command.
            (This command has a cooldown of 1 hour.)""")
        marriage = ctx.character_data["marriage"]
        if not marriage:
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(_("Can't produce a child alone, can you?"))
        async with self.bot.pool.acquire() as conn:
            names = await conn.fetch(
                'SELECT name FROM children WHERE "mother"=$1 OR "father"=$1;',
                ctx.author.id,
            )
            spouse = await conn.fetchval(
                'SELECT lovescore FROM profile WHERE "user"=$1;', marriage)
        max_ = self.get_max_kids(ctx.character_data["lovescore"] + spouse)
        if len(names) >= max_:
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(
                _("You already have {max_} children. You can increase this limit by"
                  " increasing your lovescores.").format(max_=max_))
        names = [name["name"] for name in names]
        user = await self.bot.get_user_global(marriage)
        if not await ctx.confirm(
                _("{user}, do you want to make a child with {author}?").format(
                    user=user.mention, author=ctx.author.mention),
                user=user,
        ):
            return await ctx.send(_("O.o not in the mood today?"))

        if random.choice([True, False]):
            ls = random.randint(10, 50)
            await self.bot.pool.execute(
                'UPDATE profile SET "lovescore"="lovescore"+$1 WHERE "user"=$2 OR'
                ' "user"=$3;',
                ls,
                ctx.author.id,
                marriage,
            )
            return await ctx.send(
                _("You had a lovely night and gained {ls} lovescore. 😏".format(
                    ls=ls)))
        gender = random.choice(["m", "f"])
        if gender == "m":
            await ctx.send(
                _("It's a boy! Your night of love was successful! Please enter a name"
                  " for your child."))
        elif gender == "f":
            await ctx.send(
                _("It's a girl! Your night of love was successful! Please enter a"
                  " name for your child."))

        def check(msg):
            return (msg.author.id in [ctx.author.id, marriage]
                    and 1 <= len(msg.content) <= 20
                    and msg.channel.id == ctx.channel.id)

        name = None
        while not name:
            try:
                msg = await self.bot.wait_for("message",
                                              check=check,
                                              timeout=30)
                name = msg.content.replace("@", "@\u200b")
            except asyncio.TimeoutError:
                name = await self.get_random_name(gender, names)
                await ctx.send(
                    _("You didn't enter a name, so we chose {name} for you.").
                    format(name=name))
                break
            if name in names:
                await ctx.send(
                    _("One of your children already has that name, please choose"
                      " another one."))
                name = None
        async with self.bot.pool.acquire() as conn:
            await conn.execute(
                'INSERT INTO children ("mother", "father", "name", "age", "gender")'
                " VALUES ($1, $2, $3, $4, $5);",
                ctx.author.id,
                marriage,
                name,
                0,
                gender,
            )
        await ctx.send(_("{name} was born.").format(name=name))
예제 #9
0
        )
        await self.bot.delete_adventure(ctx.author)

        if not success:
            await self.bot.pool.execute(
                'UPDATE profile SET "deaths"="deaths"+1 WHERE "user"=$1;',
                ctx.author.id)
            await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                         deaths=1)
            return await ctx.send(embed=discord.Embed(
                title=_("Adventure Failed"),
                description=_("You died on your mission. Try again!"),
                colour=0xff0000,
            ))

        gold = round(random.randint(20 * num, 60 * num) * luck_multiply)

        if await self.bot.get_booster(ctx.author, "money"):
            gold = int(gold * 1.25)

        xp = random.randint(250 * num, 500 * num)
        chance_of_loot = 5 if num == 1 else 5 + 1.5 * num
        if self.bot.in_class_line(ctx.character_data["class"], "Ritualist"):
            chance_of_loot *= 2  # can be 100 in a 30

        async with self.bot.pool.acquire() as conn:
            if (random.randint(1, 1000)) > chance_of_loot * 10:
                minstat = round(num * luck_multiply)
                maxstat = round(5 + int(num * 1.5) * luck_multiply)

                item = await self.bot.create_random_item(
예제 #10
0
            participants = participants[:-(len(participants) - toremove)]
        else:
            await ctx.send(
                _("Tournament started with **{num}** entries.").format(
                    num=toremove))
        text = _("vs")
        while len(participants) > 1:
            participants = random.shuffle(participants)
            matches = list(chunks(participants, 2))

            for match in matches:
                await ctx.send(f"{match[0].mention} {text} {match[1].mention}")
                await asyncio.sleep(2)
                async with self.bot.pool.acquire() as conn:
                    val1 = sum(await self.bot.get_damage_armor_for(
                        match[0], conn=conn)) + random.randint(1, 7)
                    val2 = sum(await self.bot.get_damage_armor_for(
                        match[1], conn=conn)) + random.randint(1, 7)
                if val1 > val2:
                    winner = match[0]
                    looser = match[1]
                elif val2 > val1:
                    winner = match[1]
                    looser = match[0]
                else:
                    winner = random.choice(match)
                    looser = match[1 - match.index(winner)]
                participants.remove(looser)
                await ctx.send(
                    _("Winner of this match is {winner}!").format(
                        winner=winner.mention))
예제 #11
0
    async def _open(self,
                    ctx,
                    rarity: CrateRarity = "common",
                    amount: IntFromTo(1, 100) = 1):
        _("""`[rarity]` - the crate's rarity to open, can be common, uncommon, rare, magic or legendary; defaults to common
            `[amount]` - the amount of crates to open, may be in range from 1 to 100 at once

            Open one of your crates to receive a weapon. To check which crates contain which items, check `{prefix}help crates`.
            This command takes up a lot of space, so choose a spammy channel to open crates."""
          )
        if ctx.character_data[f"crates_{rarity}"] < amount:
            return await ctx.send(
                _("Seems like you don't have {amount} crate(s) of this rarity yet."
                  " Vote me up to get a random one or find them!").format(
                      amount=amount))

        items = []
        async with self.bot.pool.acquire() as conn:
            await self.bot.pool.execute(
                f'UPDATE profile SET "crates_{rarity}"="crates_{rarity}"-$1 WHERE'
                ' "user"=$2;',
                amount,
                ctx.author.id,
            )
            await self.bot.cache.update_profile_cols_rel(
                ctx.author.id, **{f"crates_{rarity}": -amount})
            for _i in range(amount):
                # A number to detemine the crate item range
                rand = random.randint(0, 9)
                if rarity == "common":
                    if rand < 2:  # 20% 20-30
                        minstat, maxstat = (20, 30)
                    elif rand < 5:  # 30% 10-19
                        minstat, maxstat = (10, 19)
                    else:  # 50% 1-9
                        minstat, maxstat = (1, 9)
                elif rarity == "uncommon":
                    if rand < 2:  # 20% 30-35
                        minstat, maxstat = (30, 35)
                    elif rand < 5:  # 30% 20-29
                        minstat, maxstat = (20, 29)
                    else:  # 50% 10-19
                        minstat, maxstat = (10, 19)
                elif rarity == "rare":
                    if rand < 2:  # 20% 35-40
                        minstat, maxstat = (35, 40)
                    elif rand < 5:  # 30% 30-34
                        minstat, maxstat = (30, 34)
                    else:  # 50% 20-29
                        minstat, maxstat = (20, 29)
                elif rarity == "magic":
                    if rand < 2:  # 20% 41-45
                        minstat, maxstat = (41, 45)
                    elif rand < 5:  # 30% 35-40
                        minstat, maxstat = (35, 40)
                    else:
                        minstat, maxstat = (30, 34)
                elif rarity == "legendary":  # no else because why
                    if rand < 2:  # 20% 49-50
                        minstat, maxstat = (49, 50)
                    elif rand < 5:  # 30% 46-48
                        minstat, maxstat = (46, 48)
                    else:  # 50% 41-45
                        minstat, maxstat = (41, 45)

                item = await self.bot.create_random_item(
                    minstat=minstat,
                    maxstat=maxstat,
                    minvalue=1,
                    maxvalue=250,
                    owner=ctx.author,
                    conn=conn,
                )
                items.append(item)
                await self.bot.log_transaction(
                    ctx,
                    from_=1,
                    to=ctx.author.id,
                    subject="item",
                    data={
                        "Name": item["name"],
                        "Value": item["value"]
                    },
                    conn=conn,
                )
        if amount == 1:
            embed = discord.Embed(
                title=_("You gained an item!"),
                description=_("You found a new item when opening a crate!"),
                color=0xff0000,
            )
            embed.set_thumbnail(url=ctx.author.avatar_url)
            embed.add_field(name=_("ID"), value=item["id"], inline=False)
            embed.add_field(name=_("Name"), value=item["name"], inline=False)
            embed.add_field(name=_("Type"), value=item["type"], inline=False)
            embed.add_field(name=_("Damage"),
                            value=item["damage"],
                            inline=True)
            embed.add_field(name=_("Armor"), value=item["armor"], inline=True)
            embed.add_field(name=_("Value"),
                            value=f"${item['value']}",
                            inline=False)
            embed.set_footer(
                text=_("Remaining {rarity} crates: {crates}").format(
                    crates=ctx.character_data[f"crates_{rarity}"] - 1,
                    rarity=rarity))
            await ctx.send(embed=embed)
            if rarity == "legendary":
                await self.bot.public_log(
                    f"**{ctx.author}** opened a legendary crate and received"
                    f" {item['name']} with **{item['damage'] or item['armor']}"
                    f" {'damage' if item['damage'] else 'armor'}**.")
            elif rarity == "magic" and item["damage"] + item["armor"] >= 41:
                if item["damage"] >= 41:
                    await self.bot.public_log(
                        f"**{ctx.author}** opened a magic crate and received"
                        f" {item['name']} with **{item['damage'] or item['armor']}"
                        f" {'damage' if item['damage'] else 'armor'}**.")
        else:
            stats_raw = [i["damage"] + i["armor"] for i in items]
            stats = Counter(stats_raw)
            types = Counter([i["type"] for i in items])
            most_common = "\n".join(
                [f"- {i[0]} (x{i[1]})" for i in stats.most_common(5)])
            most_common_types = "\n".join(
                [f"- {i[0]} (x{i[1]})" for i in types.most_common()])
            top = "\n".join(
                [f"- {i}" for i in sorted(stats, reverse=True)[:5]])
            average_stat = round(sum(stats_raw) / amount, 2)
            await ctx.send(
                _("Successfully opened {amount} {rarity} crates. Average stat:"
                  " {average_stat}\nMost common stats:\n```\n{most_common}\n```\nBest"
                  " stats:\n```\n{top}\n```\nTypes:\n```\n{most_common_types}\n```"
                  ).format(
                      amount=amount,
                      rarity=rarity,
                      average_stat=average_stat,
                      most_common=most_common,
                      top=top,
                      most_common_types=most_common_types,
                  ))
            if rarity == "legendary":
                await self.bot.public_log(
                    f"**{ctx.author}** opened {amount} legendary crates and received"
                    f" stats:\n```\n{most_common}\n```\nAverage: {average_stat}"
                )
            elif rarity == "magic":
                await self.bot.public_log(
                    f"**{ctx.author}** opened {amount} magic crates and received"
                    f" stats:\n```\n{most_common}\n```\nAverage: {average_stat}"
                )
예제 #12
0
파일: __init__.py 프로젝트: indij/IdleRPG
    async def battle(self,
                     ctx,
                     money: IntGreaterThan(-1) = 0,
                     enemy: MemberConverter = None):
        _("""`[money]` - A whole number that can be 0 or greater; defaults to 0
            `[enemy]` - A user who has a profile; defaults to anyone

            Fight against another player while betting money.
            To decide the fight, the players' items, race and class bonuses and an additional number from 1 to 7 are evaluated, this serves as a way to give players with lower stats a chance at winning.

            The money is removed from both players at the start of the battle. Once a winner has been decided, they will receive their money, plus the enemy's money.
            The battle lasts 30 seconds, after which the winner and loser will be mentioned.

            If both players' stats + random number are the same, the winner is decided at random.
            The battle's winner will receive a PvP win, which shows on their profile.
            (This command has a cooldown of 90 seconds.)""")
        if enemy == ctx.author:
            return await ctx.send(_("You can't battle yourself."))
        if ctx.character_data["money"] < money:
            return await ctx.send(_("You are too poor."))

        await self.bot.pool.execute(
            'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;',
            money,
            ctx.author.id,
        )
        await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                     money=-money)

        if not enemy:
            msg = await ctx.send(
                _("{author} seeks a battle! React with тЪФ now to duel them! The price"
                  " is **${money}**.").format(author=ctx.author.mention,
                                              money=money))
        else:
            msg = await ctx.send(
                _("{author} seeks a battle with {enemy}! React with тЪФ now to duel"
                  " them! The price is **${money}**.").format(
                      author=ctx.author.mention,
                      enemy=enemy.mention,
                      money=money))

        def check(r, u):
            if enemy:
                if u != enemy:
                    return False
            return (str(r.emoji) == "\U00002694" and r.message.id == msg.id
                    and u != ctx.author and not u.bot)

        await msg.add_reaction("\U00002694")
        seeking = True

        while seeking:
            try:
                _reaction, enemy_ = await self.bot.wait_for("reaction_add",
                                                            timeout=60,
                                                            check=check)
            except asyncio.TimeoutError:
                await self.bot.reset_cooldown(ctx)
                await self.bot.pool.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                             money=money)
                return await ctx.send(
                    _("Noone wanted to join your battle, {author}!").format(
                        author=ctx.author.mention))
            if await has_money(self.bot, enemy_.id, money):
                seeking = False
            else:
                enemy_ = None
                await ctx.send(
                    _("You don't have enough money to join the battle."))

        await ctx.send(
            _("Battle **{author}** vs **{enemy}** started! 30 seconds of fighting"
              " will now start!").format(author=ctx.disp,
                                         enemy=enemy_.display_name))

        await self.bot.pool.execute(
            'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;', money,
            enemy_.id)
        await self.bot.cache.update_profile_cols_rel(enemy_.id, money=-money)

        stats = [
            sum(await self.bot.get_damage_armor_for(ctx.author)) +
            random.randint(1, 7),
            sum(await self.bot.get_damage_armor_for(enemy_)) +
            random.randint(1, 7),
        ]
        players = [ctx.author, enemy_]
        if stats[0] == stats[1]:
            winner = random.choice(players)
        else:
            winner = players[stats.index(max(stats))]
        looser = players[players.index(winner) - 1]

        await asyncio.sleep(30)

        async with self.bot.pool.acquire() as conn:
            await conn.execute(
                'UPDATE profile SET "pvpwins"="pvpwins"+1, "money"="money"+$1 WHERE'
                ' "user"=$2;',
                money * 2,
                winner.id,
            )
            await self.bot.cache.update_profile_cols_rel(winner.id,
                                                         pvpwins=1,
                                                         money=money * 2)
            await self.bot.log_transaction(
                ctx,
                from_=looser.id,
                to=winner.id,
                subject="money",
                data={"Amount": money},
                conn=conn,
            )
        await ctx.send(
            _("{winner} won the battle vs {looser}! Congratulations!").format(
                winner=winner.mention, looser=looser.mention))
예제 #13
0
파일: __init__.py 프로젝트: indij/IdleRPG
    async def raidbattle(self,
                         ctx,
                         money: IntGreaterThan(-1) = 0,
                         enemy: MemberConverter = None):
        _("""`[money]` - A whole number that can be 0 or greater; defaults to 0
            `[enemy]` - A user who has a profile; defaults to anyone

            Fight against another player while betting money.
            To decide the players' stats, their items, race and class bonuses and raidstats are evaluated.

            The money is removed from both players at the start of the battle. Once a winner has been decided, they will receive their money, plus the enemy's money.
            The battle is divided into rounds, in which a player attacks. The first round's attacker is chosen randomly, all other rounds the attacker is the last round's defender.

            The battle ends if one player's HP drops to 0 (winner decided), or if 5 minutes after the battle started pass (tie).
            In case of a tie, both players will get their money back.

            The battle's winner will receive a PvP win, which shows on their profile.
            (This command has a cooldown of 5 minutes)""")
        if enemy == ctx.author:
            return await ctx.send(_("You can't battle yourself."))
        if ctx.character_data["money"] < money:
            return await ctx.send(_("You are too poor."))

        await self.bot.pool.execute(
            'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;',
            money,
            ctx.author.id,
        )
        await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                     money=-money)

        if not enemy:
            msg = await ctx.send(
                _("{author} seeks a raidbattle! React with тЪФ now to duel them! The"
                  " price is **${money}**.").format(author=ctx.author.mention,
                                                    money=money))
        else:
            msg = await ctx.send(
                _("{author} seeks a raidbattle with {enemy}! React with тЪФ now to duel"
                  " them! The price is **${money}**.").format(
                      author=ctx.author.mention,
                      enemy=enemy.mention,
                      money=money))

        def check(r, u):
            if enemy:
                if u != enemy:
                    return False
            return (str(r.emoji) == "\U00002694" and r.message.id == msg.id
                    and u != ctx.author and not u.bot)

        await msg.add_reaction("\U00002694")
        seeking = True

        while seeking:
            try:
                _reaction, enemy_ = await self.bot.wait_for("reaction_add",
                                                            timeout=60,
                                                            check=check)
            except asyncio.TimeoutError:
                await self.bot.reset_cooldown(ctx)
                await self.bot.pool.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                             money=money)
                return await ctx.send(
                    _("Noone wanted to join your raidbattle, {author}!").
                    format(author=ctx.author.mention))
            if await has_money(self.bot, enemy_.id, money):
                seeking = False
            else:
                enemy_ = None
                await ctx.send(
                    _("You don't have enough money to join the raidbattle."))

        await self.bot.pool.execute(
            'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;', money,
            enemy_.id)
        await self.bot.cache.update_profile_cols_rel(enemy_.id, money=-money)

        players = []

        async with self.bot.pool.acquire() as conn:
            for player in (ctx.author, enemy_):
                dmg, deff = await self.bot.get_raidstats(player, conn=conn)
                u = {"user": player, "hp": 250, "armor": deff, "damage": dmg}
                players.append(u)

        # players[0] is the author, players[1] is the enemy

        battle_log = deque(
            [(
                0,
                _("Raidbattle {p1} vs. {p2} started!").format(
                    p1=players[0]["user"], p2=players[1]["user"]),
            )],
            maxlen=3,
        )

        embed = discord.Embed(description=battle_log[0][1],
                              color=self.bot.config.primary_colour)

        log_message = await ctx.send(
            embed=embed)  # we'll edit this message later to avoid spam
        await asyncio.sleep(4)

        start = datetime.datetime.utcnow()
        attacker, defender = random.sample(
            players, k=2
        )  # decide a random attacker and defender for the first iteration

        while (players[0]["hp"] > 0 and players[1]["hp"] > 0
               and datetime.datetime.utcnow() <
               start + datetime.timedelta(minutes=5)):
            # this is where the fun begins
            dmg = (attacker["damage"] + Decimal(random.randint(0, 100)) -
                   defender["armor"])
            dmg = 1 if dmg <= 0 else dmg  # make sure no negative damage happens
            defender["hp"] -= dmg
            if defender["hp"] < 0:
                defender["hp"] = 0
            battle_log.append((
                battle_log[-1][0] + 1,
                _("{attacker} attacks! {defender} takes **{dmg}HP** damage.").
                format(
                    attacker=attacker["user"].mention,
                    defender=defender["user"].mention,
                    dmg=dmg,
                ),
            ))

            embed = discord.Embed(
                description=_(
                    "{p1} - {hp1} HP left\n{p2} - {hp2} HP left").format(
                        p1=players[0]["user"],
                        hp1=players[0]["hp"],
                        p2=players[1]["user"],
                        hp2=players[1]["hp"],
                    ),
                color=self.bot.config.primary_colour,
            )

            for line in battle_log:
                embed.add_field(
                    name=_("Action #{number}").format(number=line[0]),
                    value=line[1])

            await log_message.edit(embed=embed)
            await asyncio.sleep(4)
            attacker, defender = defender, attacker  # switch places

        players = sorted(players, key=lambda x: x["hp"])
        winner = players[1]["user"]
        looser = players[0]["user"]

        async with self.bot.pool.acquire() as conn:
            await conn.execute(
                'UPDATE profile SET "money"="money"+$1, "pvpwins"="pvpwins"+1 WHERE'
                ' "user"=$2;',
                money * 2,
                winner.id,
            )
            await self.bot.cache.update_profile_cols_rel(winner.id,
                                                         money=money * 2,
                                                         pvpwins=1)
            await self.bot.log_transaction(
                ctx,
                from_=looser.id,
                to=winner.id,
                subject="money",
                data={"Amount": money},
                conn=conn,
            )
        await ctx.send(
            _("{p1} won the raidbattle vs {p2}! Congratulations!").format(
                p1=winner.mention, p2=looser.mention))
예제 #14
0
    async def trickortreat(self, ctx):
        _(
            # xgettext: no-python-format
            """Walk around the houses and scare the residents! Maybe they have a gift for you?

            This command requires two players, one that is waiting and one that rings at the door.
            If you are the one waiting, you will get a direct message from the bot later, otherwise you will get a reply immediately.

            There is a 50% chance you will receive a halloween bag from the other person.

            (This command has a cooldown of 3h)""")
        waiting = self.waiting
        if not waiting:
            self.waiting = ctx.author
            return await ctx.send(
                _("You walk around the houses... Noone is there... *yet*"))
        self.waiting = None
        async with self.bot.pool.acquire() as conn:
            if random.randint(0, 1) == 1:
                await ctx.send(
                    _("You walk around the houses and ring at {waiting}'s house!"
                      " That's a trick or treat bag for you, yay!").format(
                          waiting=waiting))
                await conn.execute(
                    'UPDATE profile SET "trickortreat"="trickortreat"+1 WHERE'
                    ' "user"=$1;',
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                             trickortreat=1)
            else:
                await ctx.send(
                    _("You walk around the houses and ring at {waiting}'s house!"
                      " Sadly they don't have anything for you...").format(
                          waiting=waiting))
            try:
                if random.randint(0, 1) == 1:
                    await waiting.send(
                        "The waiting was worth it: {author} rang! That's a trick or"
                        " treat bag for you, yay!".format(author=ctx.author))
                    await conn.execute(
                        'UPDATE profile SET "trickortreat"="trickortreat"+1 WHERE'
                        ' "user"=$1;',
                        waiting.id,
                    )
                    await self.bot.cache.update_profile_cols_rel(
                        waiting.id, trickortreat=1)
                else:
                    await waiting.send(
                        "{author} rings at your house, but... Nothing for you! 👻"
                        .format(author=ctx.author))
            except discord.Forbidden:
                pass

            if random.randint(1, 100) < 5:
                backgrounds = await conn.fetchval(
                    'UPDATE profile SET "backgrounds"=array_append("backgrounds", $1) WHERE "user"=$2 RETURNING "backgrounds";',
                    "https://i.imgur.com/dJqwM1H.png",
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_abs(
                    ctx.author.id, backgrounds=backgrounds)
                await ctx.send(
                    _("🎃 As you step out of the door, you open your candy and plastic reveals an ancient image on top of a chocolate bar, passed along for generations. You decide to keep it in your `{prefix}eventbackground`s."
                      ).format(prefix=ctx.prefix, ))
예제 #15
0
         _("Noone heard you!"),
         _("Your voice has made them screw off."),
         _("Even a donkey would've been a better follower than you."),
     ])
     val = 0
 elif rand == 1:
     val = random.randint(1, 500)
     message = random.choice([
         _("„Rather lousy, but okay“, they said."),
         _("You were a little sleepy."),
         _("They were a little amused about your singing."),
         _("Hearing the same prayer over and over again made them tired."
           ),
     ])
 elif rand == 2:
     val = random.randint(0, 500) + 500
     message = random.choice([
         _("Your Gregorian chants were amazingly well sung."),
         _("Even the birds joined in your singing."),
         _("The other gods applauded while your god noted down the best"
           " mark."),
         _("Rarely have you had a better day!"),
     ])
 if val > 0:
     await self.bot.pool.execute(
         'UPDATE profile SET "favor"="favor"+$1 WHERE "user"=$2;',
         val,
         ctx.author.id,
     )
     await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                  favor=val)
예제 #16
0
    async def activeadventure(self, ctx):
        _(
            # xgettext: no-python-format
            """Active adventures will put you into a 15x15 randomly generated maze. You will begin in the top left corner (0,0) and your goal is to find the exit in the bottom right corner (14,14)
            You control your character with the arrow reactions below the message.

            You have 1000HP. The adventure ends when you find the exit or your HP drop to zero.
            You can lose HP by getting damaged by traps or enemies.

            The maze contains safe spaces and treasures but also traps and enemies.
            Each space has a 10% chance of being a trap. If a space does not have a trap, it has a 10% chance of having an enemy.
            Each maze has 5 treasure chests.

            Traps can damage you from 30 to 120 HP.
            Enemy damage is based on your own damage. During enemy fights, you can attack (⚔️), defend (🛡️) or recover HP (❤️)
            Treasure chests can have gold up to 25 times your attack + defense.

            If you reach the end, you will receive a special treasure with gold up to 100 times your attack + defense.

            (It is recommended to draw a map of the maze)
            (This command has a cooldown of 30 minutes)""")
        if not await ctx.confirm(
                _("You are going to be in a labyrinth of size 15x15. There are enemies,"
                  " treasures and hidden traps. Reach the exit in the bottom right corner"
                  " for a huge extra bonus!\nAre you ready?\n\nTip: Use a silent channel"
                  " for this, you may want to read all the messages I will send."
                  )):
            return

        msg = await ctx.send(_("**Generating a maze...**"))

        maze = Maze.generate(15, 15)
        direction_emojis = {
            "n": "\U00002b06",
            "e": "\U000027a1",
            "s": "\U00002b07",
            "w": "\U00002b05",
        }
        direction_emojis_inverse = {
            val: key
            for key, val in direction_emojis.items()
        }
        direction_names = {
            "n": _("North"),
            "e": _("East"),
            "s": _("South"),
            "w": _("West"),
        }
        all_directions = set(direction_names.keys())
        x = 0
        y = 0

        attack, defense = await self.bot.get_damage_armor_for(ctx.author)

        attack = int(attack)
        defense = int(defense)

        hp = 1000

        def free(cell):
            return all_directions - cell.walls

        def fmt_direction(direction):
            return direction_names[direction]

        def player_pos():
            return maze[x, y]

        def is_at_end():
            return x == 14 and y == 14

        def move(x, y, direction):
            if direction == "n":
                y = y - 1
            elif direction == "e":
                x = x + 1
            elif direction == "s":
                y = y + 1
            elif direction == "w":
                x = x - 1
            return x, y

        async def wait_for_move():
            possible = free(player_pos())
            needed = [direction_emojis[direction] for direction in possible]
            try:
                await msg.clear_reactions()
            except discord.Forbidden:
                for r in msg.reactions:
                    if str(r.emoji) not in needed:
                        await msg.remove_reaction(r, ctx.guild.me)
                for r in needed:
                    if r not in [str(r.emoji) for r in msg.reactions]:
                        await msg.add_reaction(r)
            else:
                for direction in possible:
                    await msg.add_reaction(direction_emojis[direction])

            def check(evt):
                return (evt.user_id == ctx.author.id
                        and evt.message_id == msg.id
                        and direction_emojis_inverse.get(str(evt.emoji),
                                                         None) in possible)

            evt = await self.bot.wait_for("raw_reaction_add",
                                          check=check,
                                          timeout=30)

            return direction_emojis_inverse[str(evt.emoji)]

        async def update():
            text = ""
            pos = player_pos()
            for direction in ("n", "e", "s", "w"):
                side = fmt_direction(direction)
                fake_x, fake_y = move(x, y, direction)
                fake_cell = maze[fake_x, fake_y]
                if direction in pos.walls:
                    text2 = _("To the {side} is a wall.").format(side=side)
                elif fake_cell.enemy:
                    text2 = _("To the {side} is an enemy.").format(side=side)
                elif fake_cell.treasure:
                    text2 = _("To the {side} is a treasure.").format(side=side)
                else:
                    text2 = _("To the {side} is a floor.").format(side=side)
                text = f"{text}\n{text2}"

            text2 = _("You are on {hp} HP").format(hp=hp)
            text = f"{text}\n\n{text2}"

            await msg.edit(content=text)

        async def handle_specials(hp):
            cell = player_pos()
            if cell.trap:
                damage = random.randint(30, 120)
                await ctx.send(
                    _("You stepped on a trap and took {damage} damage!").
                    format(damage=damage))
                cell.trap = False  # Remove the trap
                return hp - damage
            elif cell.treasure:
                val = attack + defense
                money = random.randint(val, val * 25)
                async with self.bot.pool.acquire() as conn:
                    await conn.execute(
                        'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                        money,
                        ctx.author.id,
                    )
                    await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                                 money=money)
                    await self.bot.log_transaction(
                        ctx,
                        from_=1,
                        to=ctx.author.id,
                        subject="money",
                        data={"Amount": money},
                        conn=conn,
                    )
                await ctx.send(
                    _("You found a treasure with **${money}** inside!").format(
                        money=money))
                cell.treasure = False
            elif cell.enemy:
                emojis = {
                    "\U00002694": "attack",
                    "\U0001f6e1": "defend",
                    "\U00002764": "recover",
                }

                def to_bar(hp):
                    fields = hp // 100
                    return f"[{'▯' * fields}{'▮' * (10 - fields)}]"

                def is_valid_move(evt):
                    return (evt.message_id == msg.id
                            and evt.user_id == ctx.author.id
                            and str(evt.emoji) in emojis)

                enemy = _("Enemy")
                enemy_hp = 1000
                heal_hp = round(attack * 0.25) or 1
                min_dmg = round(attack * 0.5)
                max_dmg = round(attack * 1.5)
                status1 = _("The Fight started")
                status2 = ""

                await msg.clear_reactions()
                for emoji in emojis:
                    await msg.add_reaction(emoji)

                while enemy_hp > 0 and hp > 0:
                    await msg.edit(content=f"""\
```
{ctx.author.name}{" " * (38 - len(ctx.author.name) - len(enemy))}{enemy}
------------++++++++++++++------------
{to_bar(hp)}  {hp}  {enemy_hp}    {to_bar(enemy_hp)}

{status1}
{status2}
```""")

                    evt = await self.bot.wait_for("raw_reaction_add",
                                                  check=is_valid_move,
                                                  timeout=30)

                    try:
                        await msg.remove_reaction(evt.emoji,
                                                  discord.Object(evt.user_id))
                    except discord.Forbidden:
                        pass

                    enemy_move = random.choice(["attack", "defend", "recover"])
                    player_move = emojis[str(evt.emoji)]

                    if enemy_move == "recover":
                        enemy_hp += heal_hp
                        enemy_hp = 1000 if enemy_hp > 1000 else enemy_hp
                        status1 = _("The Enemy healed themselves for {hp} HP"
                                    ).format(hp=heal_hp)
                    if player_move == "recover":
                        hp += heal_hp
                        hp = 1000 if hp > 1000 else hp
                        status2 = _("You healed yourself for {hp} HP").format(
                            hp=heal_hp)
                    if (enemy_move == "attack" and player_move
                            == "defend") or (enemy_move == "defend"
                                             and player_move == "attack"):
                        status1 = _("Attack blocked.")
                        status2 = ""
                    if enemy_move == "attack" and player_move != "defend":
                        eff = random.randint(min_dmg, max_dmg)
                        hp -= eff
                        status1 = _("The Enemy hit you for {dmg} damage"
                                    ).format(dmg=eff)
                    if player_move == "attack" and enemy_move != "defend":
                        enemy_hp -= attack
                        status2 = _("You hit the enemy for {dmg} damage"
                                    ).format(dmg=attack)

                if enemy_hp <= 0:
                    cell.enemy = False

            return hp

        while not is_at_end():
            await update()
            try:
                direction = await wait_for_move()
            except asyncio.TimeoutError:
                return await msg.edit(content=_("Timed out."))
            x, y = move(x, y,
                        direction)  # Python namespacing sucks, to be honest
            try:
                hp = await handle_specials(hp
                                           )  # Should've used a class for this
            except asyncio.TimeoutError:
                return await msg.edit(content=_("Timed out."))
            if hp <= 0:
                return await ctx.send(_("You died."))

        val = attack + defense
        money = random.randint(val * 5, val * 100)
        async with self.bot.pool.acquire() as conn:
            await conn.execute(
                'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                money,
                ctx.author.id,
            )
            await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                         money=money)
            await self.bot.log_transaction(
                ctx,
                from_=1,
                to=ctx.author.id,
                subject="money",
                data={"Amount": money},
                conn=conn,
            )

        await ctx.send(
            _("You have reached the exit and were rewarded **${money}** for getting"
              " out!").format(money=money))
예제 #17
0
class Gods(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.bot.gods = {god["user"]: god for god in self.bot.config.gods}

    @has_god()
    @has_char()
    @user_cooldown(180, identifier="sacrificeexchange")
    @commands.command(brief=_("Sacrifice loot for favor"))
    @locale_doc
    async def sacrifice(self, ctx, *loot_ids: int):
        _("""`[loot_ids...]` - The loot IDs to sacrifice, can be one or multiple IDs separated by space; defaults to all loot

            Sacrifice loot to your God to gain favor points.

            If no loot IDs are given with this command, all loot you own will be sacrificed.
            You can see your current loot with `{prefix}loot`.

            Only players, who follow a God can use this command.""")
        async with self.bot.pool.acquire() as conn:
            if not loot_ids:
                value, count = await conn.fetchval(
                    'SELECT (SUM("value"), COUNT(*)) FROM loot WHERE "user"=$1;',
                    ctx.author.id,
                )
                if count == 0:
                    await self.bot.reset_cooldown(ctx)
                    return await ctx.send(_("You don't have any loot."))
                if not await ctx.confirm(
                        _("This will sacrifice all of your loot and give {value} favor."
                          " Continue?").format(value=value)):
                    return
            else:
                value, count = await conn.fetchval(
                    'SELECT (SUM("value"), COUNT("value")) FROM loot WHERE "id"=ANY($1)'
                    ' AND "user"=$2;',
                    loot_ids,
                    ctx.author.id,
                )

                if not count:
                    return await ctx.send(
                        _("You don't own any loot items with the IDs: {itemids}"
                          ).format(itemids=", ".join(
                              [str(loot_id) for loot_id in loot_ids])))
            class_ = ctx.character_data["class"]
            for class_ in ctx.character_data["class"]:
                c = from_string(class_)
                if c and c.in_class_line(Ritualist):
                    value = round(value * Decimal(1 + 0.05 * c.class_grade()))

            if len(loot_ids) > 0:
                await conn.execute(
                    'DELETE FROM loot WHERE "id"=ANY($1) AND "user"=$2;',
                    loot_ids,
                    ctx.author.id,
                )
            else:
                await conn.execute('DELETE FROM loot WHERE "user"=$1;',
                                   ctx.author.id)
            await conn.execute(
                'UPDATE profile SET "favor"="favor"+$1 WHERE "user"=$2;',
                value,
                ctx.author.id,
            )
            await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                         favor=int(value))

            await self.bot.log_transaction(
                ctx,
                from_=ctx.author.id,
                to=2,
                subject="sacrifice",
                data={
                    "Item-Count": count,
                    "Amount": value
                },
                conn=conn,
            )
        await ctx.send(
            _("You prayed to {god}, and they accepted your {count} sacrificed loot"
              " item(s). Your standing with the god has increased by **{points}**"
              " points.").format(god=ctx.character_data["god"],
                                 count=count,
                                 points=value))

    @has_char()
    @user_cooldown(180)  # to prevent double invoke
    @commands.command(brief=_("Choose or change your God"))
    @locale_doc
    async def follow(self, ctx):
        _("""Choose a God or change your current God for a reset point.
            Every player gets 2 reset points when they start playing, you cannot get any more.

            Following a God allows your `{prefix}luck` to fluctuate, check `{prefix}help luck` to see the exact effects this will have on your gameplay.
            If you don't have any reset points left, or became Godless, you cannot follow another God.

            (This command has a cooldown of 3 minutes.)""")
        if not has_no_god(ctx):
            if ctx.character_data["reset_points"] < 1:
                return await ctx.send(_("You have no more reset points."))
            if not await ctx.confirm(
                    _("You already chose a god. This change now will cost you a reset"
                      " point. Are you sure?")):
                return
        if ctx.character_data["reset_points"] < 0:
            return await ctx.send(
                "You became Godless and cannot follow a God anymore.")
        embeds = [
            discord.Embed(
                title=god["name"],
                description=god["description"],
                color=self.bot.config.game.primary_colour,
            ) for god in self.bot.gods.values()
        ]
        god = await self.bot.paginator.ChoosePaginator(
            extras=embeds,
            choices=[g["name"] for g in self.bot.gods.values()]).paginate(ctx)

        if not await ctx.confirm(
                _("""\
⚠ **Warning**: When you have a God, your luck will change (**including decreasing it!**)
This impacts your adventure success chances amongst other things.

Are you sure you want to follow {god}?""").format(god=god)):
            return

        async with self.bot.pool.acquire() as conn:
            if (await self.bot.cache.get_profile_col(
                    ctx.author.id, "reset_points", conn=conn) < 0):
                return await ctx.send(
                    _("You became Godless while using this command. Following a God"
                      " is not allowed after that."))
            if not has_no_god(ctx):
                await conn.execute(
                    'UPDATE profile SET "reset_points"="reset_points"-$1 WHERE'
                    ' "user"=$2;',
                    1,
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                             reset_points=-1)
            await conn.execute('UPDATE profile SET "god"=$1 WHERE "user"=$2;',
                               god, ctx.author.id)
            await self.bot.cache.update_profile_cols_abs(ctx.author.id,
                                                         god=god)

        await ctx.send(_("You are now a follower of {god}.").format(god=god))

    @has_char()
    @has_god()
    @commands.command(brief=_("Unfollow your God and become Godless"))
    @locale_doc
    async def unfollow(self, ctx):
        _("""Unfollow your current God and become Godless. **This is permanent!**

            Looking to change your God instead? Simply use `{prefix}follow` again.

            Once you become Godless, all your reset points and your God are removed.
            Becoming Godless does not mean that your luck returns to 1.00 immediately, it changes along with everyone else's luck on Monday."""
          )
        if ctx.character_data["reset_points"] < 0:
            # this shouldn't happen in normal play, but you never know
            return await ctx.send(_("You already became Godless before."))

        if not await ctx.confirm(
                _("""\
    ⚠ **Warning**: After unfollowing your God, **you cannot follow any God anymore** and will remain Godless.
    If your luck is below average and you decided to unfollow, know that **your luck will not return to 1.0 immediately**.

    Are you sure you want to become Godless?""")):
            return await ctx.send(
                _("{god} smiles proudly down upon you.").format(
                    god=ctx.character_data["god"]))

        await self.bot.pool.execute(
            'UPDATE profile SET "favor"=0, "god"=NULL, "reset_points"=-1 WHERE'
            ' "user"=$1;',
            ctx.author.id,
        )
        await self.bot.cache.update_profile_cols_abs(ctx.author.id,
                                                     favor=0,
                                                     god="",
                                                     reset_points=-1)

        await ctx.send(_("You are now Godless."))

    @has_god()
    @has_char()
    @next_day_cooldown()
    @commands.command(brief=_("Pray to your God to gain favor"))
    @locale_doc
    async def pray(self, ctx):
        _(
            # xgettext: no-python-format
            """Pray to your God in order to gain a random amont of favor points, ranging from 0 to 1000.

            There is a 33% chance you will gain 0 favor, a 33% chance to gain anywhere from 0 to 500 favor and a 33% chance to gain anywhere from 500 to 1000 favor.

            (This command has a cooldown until 12am UTC.)""")
        if (rand := random.randint(0, 2)) == 0:
            message = random.choice([
                _("They obviously didn't like your prayer!"),
                _("Noone heard you!"),
                _("Your voice has made them screw off."),
                _("Even a donkey would've been a better follower than you."),
            ])
            val = 0
        elif rand == 1:
            val = random.randint(1, 500)
            message = random.choice([
                _("„Rather lousy, but okay“, they said."),
                _("You were a little sleepy."),
                _("They were a little amused about your singing."),
                _("Hearing the same prayer over and over again made them tired."
                  ),
            ])
예제 #18
0
        async def handle_specials(hp):
            cell = player_pos()
            if cell.trap:
                damage = random.randint(30, 120)
                await ctx.send(
                    _("You stepped on a trap and took {damage} damage!").
                    format(damage=damage))
                cell.trap = False  # Remove the trap
                return hp - damage
            elif cell.treasure:
                val = attack + defense
                money = random.randint(val, val * 25)
                async with self.bot.pool.acquire() as conn:
                    await conn.execute(
                        'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                        money,
                        ctx.author.id,
                    )
                    await self.bot.cache.update_profile_cols_rel(ctx.author.id,
                                                                 money=money)
                    await self.bot.log_transaction(
                        ctx,
                        from_=1,
                        to=ctx.author.id,
                        subject="money",
                        data={"Amount": money},
                        conn=conn,
                    )
                await ctx.send(
                    _("You found a treasure with **${money}** inside!").format(
                        money=money))
                cell.treasure = False
            elif cell.enemy:
                emojis = {
                    "\U00002694": "attack",
                    "\U0001f6e1": "defend",
                    "\U00002764": "recover",
                }

                def to_bar(hp):
                    fields = hp // 100
                    return f"[{'▯' * fields}{'▮' * (10 - fields)}]"

                def is_valid_move(evt):
                    return (evt.message_id == msg.id
                            and evt.user_id == ctx.author.id
                            and str(evt.emoji) in emojis)

                enemy = _("Enemy")
                enemy_hp = 1000
                heal_hp = round(attack * 0.25) or 1
                min_dmg = round(attack * 0.5)
                max_dmg = round(attack * 1.5)
                status1 = _("The Fight started")
                status2 = ""

                await msg.clear_reactions()
                for emoji in emojis:
                    await msg.add_reaction(emoji)

                while enemy_hp > 0 and hp > 0:
                    await msg.edit(content=f"""\
```
{ctx.author.name}{" " * (38 - len(ctx.author.name) - len(enemy))}{enemy}
------------++++++++++++++------------
{to_bar(hp)}  {hp}  {enemy_hp}    {to_bar(enemy_hp)}

{status1}
{status2}
```""")

                    evt = await self.bot.wait_for("raw_reaction_add",
                                                  check=is_valid_move,
                                                  timeout=30)

                    try:
                        await msg.remove_reaction(evt.emoji,
                                                  discord.Object(evt.user_id))
                    except discord.Forbidden:
                        pass

                    enemy_move = random.choice(["attack", "defend", "recover"])
                    player_move = emojis[str(evt.emoji)]

                    if enemy_move == "recover":
                        enemy_hp += heal_hp
                        enemy_hp = 1000 if enemy_hp > 1000 else enemy_hp
                        status1 = _("The Enemy healed themselves for {hp} HP"
                                    ).format(hp=heal_hp)
                    if player_move == "recover":
                        hp += heal_hp
                        hp = 1000 if hp > 1000 else hp
                        status2 = _("You healed yourself for {hp} HP").format(
                            hp=heal_hp)
                    if (enemy_move == "attack" and player_move
                            == "defend") or (enemy_move == "defend"
                                             and player_move == "attack"):
                        status1 = _("Attack blocked.")
                        status2 = ""
                    if enemy_move == "attack" and player_move != "defend":
                        eff = random.randint(min_dmg, max_dmg)
                        hp -= eff
                        status1 = _("The Enemy hit you for {dmg} damage"
                                    ).format(dmg=eff)
                    if player_move == "attack" and enemy_move != "defend":
                        enemy_hp -= attack
                        status2 = _("You hit the enemy for {dmg} damage"
                                    ).format(dmg=attack)

                if enemy_hp <= 0:
                    cell.enemy = False

            return hp
예제 #19
0
    async def familyevent(self, ctx):
        _("""Allow your children to do something, this includes a multitude of events.

            Every time you or your partner uses this command, your children:
              - have an 8/23 chance to grow older by one year
              - have a 4/23 chance to be renamed
              - have a 4/23 chance to take up to 1/64th of your money
              - have a 4/23 chance to give you up to 1/64th of your current money extra
              - have a 2/23 chance to find a random crate for you:
                + 500/761 (65%) chance for a common crate
                + 200/761 (26%) chance for an uncommon crate
                + 50/761 (6%) chance for a rare crate
                + 10/761 (1%) chance for a magic crate
                + 1/761 (0.1%) chance for a legendary crate
              - have a 1/23 chance to die

            In each event you will know what happened.

            Only players who are married and have children can use this command.
            (This command has a cooldown of 30 minutes.)""")
        if not ctx.character_data["marriage"]:
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(_("You're lonely."))
        children = await self.bot.pool.fetch(
            'SELECT * FROM children WHERE "mother"=$1 OR "father"=$1;',
            ctx.author.id)
        if not children:
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(_("You don't have kids yet."))
        target = random.choice(children)
        event = random.choice(["death"] + ["age"] * 8 + ["namechange"] * 4 +
                              ["crate"] * 2 + ["moneylose"] * 4 +
                              ["moneygain"] * 4)
        if event == "death":
            cause = random.choice([
                _("They died because of a shampoo overdose!"),
                _("They died of lovesickness..."),
                _("They've died of age."),
                _("They died of loneliness."),
                _("A horde of goblins got them."),
                _("They have finally decided to move out after all these years,"
                  " but couldn't survive a second alone."),
                _("Spontaneous combustion removed them from existence."),
                _("While exploring the forest, they have gotten lost."),
                _("They've left through a portal into another dimension..."),
                _("The unbearable pain of stepping on a Lego\© brick killed them."  # noqa
                  ),
                _("You heard a landmine going off nearby..."),
                _("They have been abducted by aliens!"),
                _("The Catholic Church got them..."),
                _("They starved after becoming a communist."),
            ])
            await self.bot.pool.execute(
                'DELETE FROM children WHERE "name"=$1 AND ("mother"=$2 OR "father"=$2)'
                ' AND "age"=$3;',
                target["name"],
                ctx.author.id,
                target["age"],
            )
            return await ctx.send(
                _("{name} died at the age of {age}! {cause}").format(
                    name=target["name"], age=target["age"], cause=cause))
        elif event == "moneylose":
            cause = random.choice([
                _("fell in love with a woman on the internet, but the woman was a"
                  " man and stole their money."),
                _("has been arrested and had to post bail."),
                _("bought fortnite skins with your credit card."),
                _("decided to become communist and gave the money to others."),
                _("was caught pickpocketing and you had to pay the fine."),
                _("gave it to a beggar."),
                _("borrowed it to attend the local knights course."),
                _("spent it in the shop."),
                _("bought some toys."),
                _("has gambling addiction and lost the money..."),
            ])
            money = random.randint(0, int(ctx.character_data["money"] / 64))
            await self.bot.pool.execute(
                'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;',
                money,
                ctx.author.id,
            )
            await self.bot.log_transaction(ctx,
                                           from_=ctx.author.id,
                                           to=2,
                                           subject="money",
                                           data={"Amount": -money})

            return await ctx.send(
                _("You lost ${money} because {name} {cause}").format(
                    money=money, name=target["name"], cause=cause))
        elif event == "moneygain":
            cause = random.choice([
                _("finally found a job!"),
                _("won a lottery."),
                _("sold their toys."),
                _("got money from another kid that decided to become communist."
                  ),
                _("stole it from a traveller."),
                _("finished a quest with a money reward."),
                _("used dark magic to summon some money."),
                _("looted a local warehouse and sold the wares."),
                _("solved an enigma with a money reward."),
            ])
            money = random.randint(0, int(ctx.character_data["money"] / 64))
            await self.bot.pool.execute(
                'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                money,
                ctx.author.id,
            )
            await self.bot.log_transaction(ctx,
                                           from_=1,
                                           to=ctx.author.id,
                                           subject="money",
                                           data={"Amount": money})
            return await ctx.send(
                _("{name} gave you ${money}, they {cause}").format(
                    name=target["name"], money=money, cause=cause))
        elif event == "crate":
            type_ = random.choice(["common"] * 500 + ["uncommon"] * 200 +
                                  ["rare"] * 50 + ["magic"] * 10 +
                                  ["legendary"])
            await self.bot.pool.execute(
                f'UPDATE profile SET "crates_{type_}"="crates_{type_}"+1 WHERE'
                ' "user"=$1;',
                ctx.author.id,
            )
            emoji = getattr(self.bot.cogs["Crates"].emotes, type_)
            await self.bot.log_transaction(
                ctx,
                from_=ctx.author.id,
                to=2,
                subject="crates",
                data={
                    "Rarity": type_,
                    "Amount": 1
                },
            )
            return await ctx.send(
                _("{name} found a {emoji} {type_} crate for you!").format(
                    name=target["name"], emoji=emoji, type_=type_))
        elif event == "age":
            await self.bot.pool.execute(
                'UPDATE children SET "age"="age"+1 WHERE "name"=$1 AND ("mother"=$2 OR'
                ' "father"=$2) AND "age"=$3;',
                target["name"],
                ctx.author.id,
                target["age"],
            )
            return await ctx.send(
                _("{name} is now {age} years old.").format(name=target["name"],
                                                           age=target["age"] +
                                                           1))
        elif event == "namechange":
            await ctx.send(
                _("{name} can be renamed! Enter a new name:").format(
                    name=target["name"]))
            names = [c["name"] for c in children]
            names.remove(target["name"])

            def check(msg):
                return (msg.author.id
                        in [ctx.author.id, ctx.character_data["marriage"]]
                        and msg.channel.id == ctx.channel.id
                        and 0 < len(msg.content) <= 20)

            name = None
            while not name:
                try:
                    msg = await self.bot.wait_for("message",
                                                  check=check,
                                                  timeout=30)
                    name = msg.content.replace("@", "@\u200b")
                except asyncio.TimeoutError:
                    return await ctx.send(_("You didn't enter a name."))
                if name in names:
                    await ctx.send(
                        _("One of your children already has that name, please choose"
                          " another one."))
                    name = None
            await self.bot.pool.execute(
                'UPDATE children SET "name"=$1 WHERE "name"=$2 AND ("mother"=$3 OR'
                ' "father"=$3) AND "age"=$4;',
                name,
                target["name"],
                ctx.author.id,
                target["age"],
            )
            if name == target["name"]:
                return await ctx.send(_("You didn't change their name."))
            return await ctx.send(
                _("{old_name} is now called {new_name}.").format(
                    old_name=target["name"], new_name=name))
예제 #20
0
    async def chocolate(self, ctx):
        _("""Opens one of your chocolate boxes.
            These boxes have a 1/4 chance of containing money, a 1/4 chance for an item and a 2/4 chance for lovescore."""
          )
        if ctx.character_data["chocolates"] <= 0:
            return await ctx.send(_("You have no chocolate boxes left."))
        await self.bot.pool.execute(
            'UPDATE profile SET "chocolates"="chocolates"-1 WHERE "user"=$1',
            ctx.author.id,
        )

        prize = random.choice(["money", "item", "lovescore", "lovescore"])
        if prize == "money":
            money = random.randint(1, 10) * 1000
            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                await self.bot.log_transaction(
                    ctx,
                    from_=1,
                    to=ctx.author.id,
                    subject="money",
                    data={"Amount": money},
                    conn=conn,
                )
            return await ctx.send(
                _("The chocolate box contained **${money}!**").format(
                    money=money))
        elif prize == "lovescore":
            lovescore = random.randint(5, 10) * 1000
            await self.bot.pool.execute(
                'UPDATE profile SET "lovescore"="lovescore"+$1 WHERE "user"=$2;',
                lovescore,
                ctx.author.id,
            )
            return await ctx.send(
                _("The chocolate box contained **{lovescore} lovescore points!**"
                  ).format(lovescore=lovescore))
        else:
            minstat = round(ctx.character_data["lovescore"] / 250_000) or 1
            maxstat = round(ctx.character_data["lovescore"] / 100_000) or 1

            item = await self.bot.create_random_item(
                minstat=minstat if minstat < 30 else 30,
                maxstat=maxstat if maxstat < 30 else 30,
                minvalue=1,
                maxvalue=250,
                owner=ctx.author,
                insert=False,
            )
            item["name"] = self.get_valentine_name(item["type_"])

            async with self.bot.pool.acquire() as conn:
                item = await self.bot.create_item(**item, conn=conn)
                await self.bot.log_transaction(
                    ctx,
                    from_=1,
                    to=ctx.author.id,
                    subject="item",
                    data={
                        "Name": item["name"],
                        "Value": item["value"]
                    },
                    conn=conn,
                )
            embed = discord.Embed(
                title=_("You gained an item!"),
                description=_("The chocolate box contained an item!"),
                color=0xFF0000,
            )
            embed.set_thumbnail(url=ctx.author.display_avatar.url)
            embed.add_field(name=_("ID"), value=item["id"], inline=False)
            embed.add_field(name=_("Name"), value=item["name"], inline=False)
            embed.add_field(name=_("Type"), value=item["type"], inline=False)
            if item["type"] == "Shield":
                embed.add_field(name=_("Armor"),
                                value=item["armor"],
                                inline=True)
            else:
                embed.add_field(name=_("Damage"),
                                value=item["damage"],
                                inline=True)
            embed.add_field(name=_("Value"),
                            value=f"${item['value']}",
                            inline=False)
            embed.set_footer(text=_("You have {chocolates} left").format(
                chocolates=ctx.character_data["chocolates"] - 1))
            return await ctx.send(embed=embed)
예제 #21
0
    async def daily(self, ctx):
        _(
            """Get your daily reward. Depending on your streak, you will gain better rewards.

            After ten days, your rewards will reset. Day 11 and day 1 have the same rewards.
            The rewards will either be money (2/3 chance) or crates (1/3 chance).

            The possible rewards are:

              __Day 1__
              $50 or 1-6 common crates

              __Day 2__
              $100 or 1-5 common crates

              __Day 3__
              $200 or 1-4 common (99%) or uncommon (1%) crates

              __Day 4__
              $400 or 1-4 common (99%) or uncommon (1%) crates

              __Day 5__
              $800 or 1-4 common (99%) or uncommon (1%) crates

              __Day 6__
              $1,600 or 1-3 common (80%), uncommon (19%) or rare (1%) crates

              __Day 7__
              $3,200 or 1-2 uncommon (80%), rare (19%) or magic (1%) crates

              __Day 8__
              $6,400 or 1-2 uncommon (80%), rare (19%) or magic (1%) crates

              __Day 9__
              $12,800 or 1-2 uncommon (80%), rare (19%) or magic (1%) crates

              __Day 10__
              $25,600 or 1 rare (80%), magic (19%) or legendary (1%) crate

            If you don't use this command up to 48 hours after the first use, you will lose your streak.

            (This command has a cooldown until 12am UTC.)"""
        )
        streak = await self.bot.redis.execute("INCR", f"idle:daily:{ctx.author.id}")
        await self.bot.redis.execute(
            "EXPIRE", f"idle:daily:{ctx.author.id}", 48 * 60 * 60
        )  # 48h: after 2 days, they missed it
        money = 2 ** ((streak + 9) % 10) * 50
        # Either money or crates
        if random.randint(0, 2) > 0:
            money = 2 ** ((streak + 9) % 10) * 50
            # Silver = 1.5x
            if await user_is_patron(self.bot, ctx.author, "silver"):
                money = round(money * 1.5)
            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                await self.bot.log_transaction(
                    ctx,
                    from_=1,
                    to=ctx.author.id,
                    subject="money",
                    data={"Amount": money},
                    conn=conn,
                )
            await self.bot.cache.update_profile_cols_rel(ctx.author.id, money=money)
            txt = f"**${money}**"
        else:
            num = round(((streak + 9) % 10 + 1) / 2)
            amt = random.randint(1, 6 - num)
            types = [
                "common",
                "uncommon",
                "rare",
                "magic",
                "legendary",
                "common",
                "common",
                "common",
            ]  # Trick for -1
            type_ = random.choice(
                [types[num - 3]] * 80 + [types[num - 2]] * 19 + [types[num - 1]] * 1
            )
            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    f'UPDATE profile SET "crates_{type_}"="crates_{type_}"+$1 WHERE'
                    ' "user"=$2;',
                    amt,
                    ctx.author.id,
                )
                await self.bot.log_transaction(
                    ctx,
                    from_=1,
                    to=ctx.author.id,
                    subject="crates",
                    data={"Rarity": type_, "Amount": amt},
                    conn=conn,
                )
            await self.bot.cache.update_profile_cols_rel(
                ctx.author.id, **{f"crates_{type_}": amt}
            )
            txt = f"**{amt}** {getattr(self.bot.cogs['Crates'].emotes, type_)}"

        await ctx.send(
            _(
                "You received your daily {txt}!\nYou are on a streak of **{streak}**"
                " days!\n*Tip: `{prefix}vote` every 12 hours to get an up to legendary"
                " crate with possibly rare items!*"
            ).format(txt=txt, money=money, streak=streak, prefix=ctx.prefix)
        )
예제 #22
0
            Your steal chance is increased by evolving your class and your alliance's thief buildings, if you have an alliance that owns a city.
            If you succeed in stealing, you will steal 10% of the target's money.

            You *cannot* choose your target, it is always a random player. If the bot can't find the player's name, it will be replaced with "a traveller passing by".
            The target cannot be anyone with less than $10, yourself, or one of the Game Masters.

            Only thieves can use this command.
            (This command has a cooldown of 1 hour.)"""
        )
        if (
            buildings := await self.bot.get_city_buildings(ctx.character_data["guild"])
        ) :
            bonus = buildings["thief_building"] * 5
        else:
            bonus = 0
        if random.randint(0, 99) in range(
            1,
            self.bot.get_class_grade_from(ctx.character_data["class"], "Thief") * 8
            + 1
            + bonus,
        ):
            async with self.bot.pool.acquire() as conn:
                usr = await conn.fetchrow(
                    'SELECT "user", "money" FROM profile WHERE "money">=10 AND'
                    ' "user"!=$1 ORDER BY RANDOM() LIMIT 1;',
                    ctx.author.id,
                )

                if usr["user"] in self.bot.owner_ids:
                    return await ctx.send(
                        _(