コード例 #1
0
ファイル: adventure.py プロジェクト: Tominous/IdleRPG
    async def adventures(self, ctx):
        """A list of all adventures with success rates, name and time it takes."""
        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        all_dungeons = list(self.bot.config.adventure_times.keys())
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        damage = sword["damage"] if sword else 0
        defense = shield["armor"] if shield else 0

        msg = await ctx.send("Loading images...")

        chances = []
        for adv in all_dungeons:
            success = rpgtools.calcchance(damage,
                                          defense,
                                          adv,
                                          int(level),
                                          returnsuccess=False)
            chances.append((success[0] - success[2], success[1] + success[2]))
        thing = functools.partial(rpgtools.makeadventures, chances)
        images = await self.bot.loop.run_in_executor(None, thing)

        await msg.delete()

        files = [
            discord.File(img, filename=f"Adventure{idx + 1}.png")
            for idx, img in enumerate(images)
        ]
        pages = [
            discord.Embed().set_image(
                url=f"attachment://Adventure{idx + 1}.png")
            for idx in range(len(images))
        ]

        await self.bot.paginator.AdventurePaginator(embeds=pages,
                                                    files=files).paginate(ctx)
コード例 #2
0
 async def best(self, ctx):
     _("""Shows the best players of your guild by XP.""")
     await ctx.trigger_typing()
     async with self.bot.pool.acquire() as conn:
         guild = await conn.fetchrow(
             'SELECT * FROM guild WHERE "id"=$1;', ctx.character_data["guild"]
         )
         players = await conn.fetch(
             'SELECT "user", "name", "xp" FROM profile WHERE "guild"=$1 ORDER BY "xp" DESC LIMIT 10;',
             guild["id"],
         )
     result = ""
     for idx, profile in enumerate(players):
         charname = await rpgtools.lookup(self.bot, profile[0])
         text = _(
             "{name}, a character by `{charname}` with Level **{level}** (**{xp}** XP)"
         ).format(
             charname=charname,
             name=profile["name"],
             level=rpgtools.xptolevel(profile["xp"]),
             xp=profile["xp"],
         )
         result = f"{result}{idx + 1}. {text}\n"
     await ctx.send(
         embed=discord.Embed(
             title=_("The Best Players of {name}").format(name=guild["name"]),
             description=result,
             colour=0xE7CA01,
         )
     )
コード例 #3
0
    async def adventure(self, ctx, adventure_number: IntFromTo(1, 30)):
        _(
            """`<adventure_number>` - a whole number from 1 to 30

            Send your character on an adventure with the difficulty `<adventure_number>`.
            The adventure will take `<adventure_number>` hours if no time booster is used, and half as long if a time booster is used.

            If you are in an alliance which owns a city with adventure buildings, your adventure time will be reduced by the adventure building level in %.
            Donators' time will also be reduced:
              - 5% reduction for Silver Donators
              - 10% reduction for Gold Donators
              - 25% reduction for Emerald Donators and above

            Be sure to check `{prefix}status` to check how much time is left, or to check if you survived or died."""
        )
        if adventure_number > rpgtools.xptolevel(ctx.character_data["xp"]):
            return await ctx.send(
                _("You must be on level **{level}** to do this adventure.").format(
                    level=adventure_number
                )
            )
        time = timedelta(hours=adventure_number)

        if buildings := await self.bot.get_city_buildings(ctx.character_data["guild"]):
            time -= time * (buildings["adventure_building"] / 100)
コード例 #4
0
 async def evolve(self, ctx):
     _("""Evolve to the next level of your classes.""")
     level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
     if level < 5:
         return await ctx.send(_("Your level isn't high enough to evolve."))
     newindex = int(level / 5) - 1
     updated = 0
     new_classes = []
     for class_ in ctx.character_data["class"]:
         if class_ != "No Class":
             new_classes.append(
                 self.bot.get_class_evolves()[self.bot.get_class_line(class_)][
                     newindex
                 ]
             )
             updated += 1
         else:
             new_classes.append("No Class")
     if updated == 0:
         return await ctx.send(_("You haven't got a class yet."))
     await self.bot.pool.execute(
         'UPDATE profile SET "class"=$1 WHERE "user"=$2;', new_classes, ctx.author.id
     )
     await ctx.send(
         _("You are now a `{class1}` and a `{class2}`.").format(
             class1=new_classes[0], class2=new_classes[1]
         )
     )
コード例 #5
0
 async def is_in_guild(userid, difficulty):
     user = await self.bot.pool.fetchrow(
         'SELECT guild, xp FROM profile WHERE "user"=$1;', userid)
     if user[0] == guild["id"]:
         difficulty += int(rpgtools.xptolevel(user[1]))
         return difficulty
     return False
コード例 #6
0
 async def profile(self, ctx, *, person: User = Author):
     _("""View someone's or your own profile.""")
     await ctx.trigger_typing()
     targetid = person.id
     async with self.bot.pool.acquire() as conn:
         profile = await conn.fetchrow(
             'SELECT * FROM profile WHERE "user"=$1;', targetid
         )
         if not profile:
             return await ctx.send(
                 _("**{person}** does not have a character.").format(person=person)
             )
         sword, shield = await self.bot.get_equipped_items_for(targetid)
         ranks = await self.bot.get_ranks_for(targetid)
         mission = await self.bot.get_adventure(targetid)
         guild = await conn.fetchval(
             'SELECT name FROM guild WHERE "id"=$1;', profile["guild"]
         )
         v1 = sword["damage"] if sword else 0.0
         v2 = shield["armor"] if shield else 0.0
         damage, armor = await self.bot.generate_stats(
             targetid, v1, v2, classes=profile["class"], race=profile["race"]
         )
         extras = (damage - v1, armor - v2)
         sworddmg = f"{v1}{' (+' + str(extras[0]) + ')' if extras[0] else ''}"
         shielddef = f"{v2}{' (+' + str(extras[1]) + ')' if extras[1] else ''}"
         url = (
             f"{self.bot.config.okapi_url}/api/genprofile/beta"
             if self.bot.config.is_beta
             else f"{self.bot.config.okapi_url}/api/genprofile"
         )
         async with self.bot.trusted_session.post(
             url,
             data={
                 "name": profile["name"],
                 "color": profile["colour"],
                 "image": profile["background"],
                 "money": f"{profile['money']}",
                 "pvpWins": f"{profile['pvpwins']}",
                 "ecoRank": f"{ranks[0]}",
                 "rank": f"{ranks[1]}",
                 "level": rpgtools.xptolevel(profile["xp"]),
                 "swordDamage": sworddmg,
                 "shieldDamage": shielddef,  # Dini you f****d up
                 "swordName": sword["name"] if sword else "None Equipped",
                 "shieldName": shield["name"] if shield else "None Equipped",
                 "married": await rpgtools.lookup(self.bot, profile["marriage"])
                 or _("Not Married"),
                 "guild": guild,
                 "classes": profile["class"],
                 "icons": [
                     self.bot.get_class_line(c).lower() for c in profile["class"]
                 ],
                 "mission": f"{mission[0]} - {mission[1] if not mission[2] else _('Finished')}"
                 if mission
                 else _("No Mission"),
             },
         ) as req:
             img = BytesIO(await req.read())
     await ctx.send(file=discord.File(fp=img, filename="Profile.png"))
コード例 #7
0
ファイル: __init__.py プロジェクト: Mr-E0us-Stranger/IdleRPG
    async def status(self, ctx):
        _("""Checks your adventure status.""")
        num, time, done = ctx.adventure_data

        if not done:
            return await ctx.send(
                _("""\
You are currently on an adventure with difficulty `{difficulty}`.
Time until it completes: `{time_left}`
Adventure name: `{adventure}`""").format(
                    difficulty=num,
                    time_left=time,
                    adventure=self.bot.config.adventure_names[num],
                ))

        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        sword, shield = await self.bot.generate_stats(
            ctx.author,
            sword["damage"] if sword else 0,
            shield["armor"] if shield else 0,
            classes=ctx.character_data["class"],
            race=ctx.character_data["race"],
        )

        luck_booster = await self.bot.get_booster(ctx.author, "luck")
        current_level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
        luck_multiply = ctx.character_data["luck"]
        if (buildings := await
                self.bot.get_city_buildings(ctx.character_data["guild"])):
            bonus = buildings["adventure_building"]
コード例 #8
0
    async def adventures(self, ctx):
        _(
            """Shows all adventures, their names, descriptions, and your chances to beat them in picture form.
            Your chances are determined by your equipped items, race and class bonuses, your level and your God-given luck."""
        )
        damage, defense = await self.bot.get_damage_armor_for(ctx.author)
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        luck_booster = await self.bot.get_booster(ctx.author, "luck")

        chances = []
        for adv in range(1, 31):
            success = rpgtools.calcchance(
                damage,
                defense,
                adv,
                int(level),
                ctx.character_data["luck"],
                booster=luck_booster,
                returnsuccess=False,
            )
            chances.append(success)

        async with self.bot.trusted_session.post(
            f"{self.bot.config.external.okapi_url}/api/genadventures",
            json={"percentages": chances},
            headers={"Authorization": self.bot.config.external.okapi_token},
        ) as r:
            images = await r.json()

        pages = [discord.Embed().set_image(url=image) for image in images]

        await self.bot.paginator.Paginator(extras=pages).paginate(ctx)
コード例 #9
0
ファイル: classes.py プロジェクト: Tominous/IdleRPG
 async def get_level(self, userid):
     async with self.bot.pool.acquire() as conn:
         ret = await conn.fetchval(
             'SELECT xp FROM profile WHERE "user"=$1;', userid)
     if not ret:
         return ret
     else:
         return rpgtools.xptolevel(ret)
コード例 #10
0
    async def profile2(self, ctx, target: User = Author):
        _("""View someone's profile, not image based.""")
        rank_money, rank_xp = await self.bot.get_ranks_for(target)
        sword, shield = await self.bot.get_equipped_items_for(target)
        async with self.bot.pool.acquire() as conn:
            p_data = await conn.fetchrow(
                'SELECT * FROM profile WHERE "user"=$1;', target.id)
            if not p_data:
                return await ctx.send(
                    _("**{target}** does not have a character.").format(
                        target=target))
            mission = await self.bot.get_adventure(target)
            guild = await conn.fetchval(
                'SELECT name FROM guild WHERE "id"=$1;', p_data["guild"])
        try:
            colour = discord.Colour.from_rgb(
                *rpgtools.hex_to_rgb(p_data["colour"]))
        except ValueError:
            colour = 0x000000
        if mission:
            timeleft = str(
                mission[1]).split(".")[0] if not mission[2] else "Finished"
        sword = f"{sword['name']} - {sword['damage']}" if sword else "No sword"
        shield = f"{shield['name']} - {shield['armor']}" if shield else "No shield"
        level = rpgtools.xptolevel(p_data["xp"])
        em = discord.Embed(colour=colour, title=f"{target}: {p_data['name']}")
        em.set_thumbnail(url=target.avatar_url)
        em.add_field(
            name=_("General"),
            value=_("""\
**Money**: `${money}`
**Level**: `{level}`
**Class**: `{class_}`
**Race**: `{race}`
**PvP Wins**: `{pvp}`
**Guild**: `{guild}`""").format(
                money=p_data["money"],
                level=level,
                class_="/".join(p_data["class"]),
                race=p_data["race"],
                pvp=p_data["pvpwins"],
                guild=guild,
            ),
        )
        em.add_field(
            name=_("Ranks"),
            value=_("**Richest**: `{rank_money}`\n**XP**: `{rank_xp}`").format(
                rank_money=rank_money, rank_xp=rank_xp),
        )
        em.add_field(
            name=_("Equipment"),
            value=_("Sword: {sword}\nShield: {shield}").format(sword=sword,
                                                               shield=shield),
        )
        if mission:
            em.add_field(name=_("Mission"), value=f"{mission[0]} - {timeleft}")
        await ctx.send(embed=em)
コード例 #11
0
 async def xp(self, ctx):
     _("""Shows your current XP and level.""")
     points = ctx.character_data["xp"]
     await ctx.send(
         _("You currently have **{points} XP**, which means you are on Level **{level}**. Missing to next level: **{missing}**"
           ).format(
               points=points,
               level=rpgtools.xptolevel(points),
               missing=rpgtools.xptonextlevel(points),
           ))
コード例 #12
0
ファイル: __init__.py プロジェクト: ykron4ik/IdleRPG
 async def xp(self, ctx, user: UserWithCharacter = Author):
     _("""Shows current XP and level of a player.""")
     if user.id == ctx.author.id:
         points = ctx.character_data["xp"]
         await ctx.send(
             _("You currently have **{points} XP**, which means you are on Level **{level}**. Missing to next level: **{missing}**"
               ).format(
                   points=points,
                   level=rpgtools.xptolevel(points),
                   missing=rpgtools.xptonextlevel(points),
               ))
     else:
         points = ctx.user_data["xp"]
         await ctx.send(
             _("{user} has **{points} XP** and is on Level **{level}**. Missing to next level: **{missing}**"
               ).format(
                   user=user,
                   points=points,
                   level=rpgtools.xptolevel(points),
                   missing=rpgtools.xptonextlevel(points),
               ))
コード例 #13
0
ファイル: adventure.py プロジェクト: terror-kvothe/IdleRPG
 async def adventure(self, ctx, dungeonnumber: IntFromTo(1, 20)):
     _("""Sends your character on an adventure.""")
     if dungeonnumber > int(rpgtools.xptolevel(ctx.character_data["xp"])):
         return await ctx.send(
             _("You must be on level **{level}** to do this adventure.").
             format(level=dungeonnumber))
     time_booster = await self.bot.get_booster(ctx.author, "time")
     time = self.bot.config.adventure_times[dungeonnumber]
     if time_booster:
         time = time / 2
     await self.bot.start_adventure(ctx.author, dungeonnumber, time)
     await ctx.send(
         _("Successfully sent your character out on an adventure. Use `{prefix}status` to see the current status of the mission."
           ).format(prefix=ctx.prefix))
コード例 #14
0
ファイル: __init__.py プロジェクト: Mr-E0us-Stranger/IdleRPG
    async def adventure(self, ctx, dungeonnumber: IntFromTo(1, 30)):
        _("""Sends your character on an adventure.""")
        if dungeonnumber > int(rpgtools.xptolevel(ctx.character_data["xp"])):
            return await ctx.send(
                _("You must be on level **{level}** to do this adventure.").
                format(level=dungeonnumber))
        time_booster = await self.bot.get_booster(ctx.author, "time")
        time = self.bot.config.adventure_times[dungeonnumber]
        if time_booster:
            time = time / 2

        if (buildings := await
                self.bot.get_city_buildings(ctx.character_data["guild"])):
            time -= time * (buildings["adventure_building"] / 100)
コード例 #15
0
ファイル: classes.py プロジェクト: nsnook983/SnugRPG
 async def evolve(self, ctx):
     _("""Evolve to the next level of your class.""")
     level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
     if level < 5:
         return await ctx.send(_("Your level isn't high enough to evolve."))
     if ctx.character_data["class"] == "No Class":
         return await ctx.send(_("You haven't got a class yet."))
     newindex = int(level / 5) - 1
     newclass = self.bot.get_class_evolves()[self.bot.get_class_line(
         ctx.character_data["class"])][newindex]
     await self.bot.pool.execute(
         'UPDATE profile SET "class"=$1 WHERE "user"=$2;', newclass,
         ctx.author.id)
     await ctx.send(
         _("You are now a `{newclass}`.").format(newclass=newclass))
コード例 #16
0
ファイル: __init__.py プロジェクト: indij/IdleRPG
    async def evolve(self, ctx):
        _(
            # xgettext: no-python-format
            """Evolve your class, bringing it to the next level and giving better class bonuses.

            You can evolve every 5 levels, i.e. at level 5, level 10, level 15, level 20, level 25 and finally level 30.

            - Warriors gain +1 defense per evolution
            - Thieves gain +8% for their success chance per evolution
            - Mages gain +1 damage per evolution
            - Rangers' pets' hunted item get +3 minimum stat and +6 maximum stat per evolution
              - This means level 1 pets can hunt items from stat 3 to stat 6; level 2 pets from stat 6 to stat 12
            - Raiders gain +0.1 defense and damage raidstats
            - Ritualists gain +5% extra favor when sacrificing per evolution
            (- Paragons gain +1 damage *and* +1 defense per evolution)"""
        )
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        if level < 5:
            return await ctx.send(_("Your level isn't high enough to evolve."))
        newindex = int(level / 5) - 1
        updated = 0
        new_classes = []
        for class_ in ctx.character_data["class"]:
            if class_ != "No Class":
                new_classes.append(
                    self.bot.get_class_evolves()[self.bot.get_class_line(class_)][
                        newindex
                    ]
                )
                updated += 1
            else:
                new_classes.append("No Class")
        if updated == 0:
            return await ctx.send(_("You haven't got a class yet."))
        if ctx.character_data["class"] == new_classes:
            return await ctx.send(_("Nothing to evolve."))
        await self.bot.pool.execute(
            'UPDATE profile SET "class"=$1 WHERE "user"=$2;', new_classes, ctx.author.id
        )
        await self.bot.cache.update_profile_cols_abs(ctx.author.id, class_=new_classes)
        await ctx.send(
            _("You are now a `{class1}` and a `{class2}`.").format(
                class1=new_classes[0], class2=new_classes[1]
            )
        )
コード例 #17
0
    async def status(self, ctx):
        _(
            """Checks the remaining time of your adventures, or if you survived or died. Your chance is checked here, not in `{prefix}adventure`.
            Your chances are determined by your equipped items, race and class bonuses, your level, God-given luck and active luck boosters.

            If you are in an alliance which owns a city with an adventure building, your chance will be increased by 1% per building level.

            If you survive on your adventure, you will receive gold up to the adventure number times 60, XP up to 500 times the adventure number and either a loot or gear item.
            The chance of loot is dependent on the adventure number and whether you use the Ritualist class, [check our wiki](https://wiki.idlerpg.xyz/index.php?title=Loot) for the exact chances.

            God given luck affects the amount of gold and the gear items' damage/defense and value.

            If you are in a guild, its guild bank will receive 10% of the amount of gold extra.
            If you are married, your partner will receive a portion of your gold extra as well, [check the wiki](https://wiki.idlerpg.xyz/index.php?title=Family#Adventure_Bonus) for the exact portion."""
        )
        num, time, done = ctx.adventure_data

        if not done:
            # TODO: Embeds ftw
            return await ctx.send(
                embed=discord.Embed(
                    title=_("Adventure Status"),
                    description=_(
                        "You are currently on an adventure with difficulty"
                        " **{difficulty}**.\nTime until it completes:"
                        " **{time_left}**\nAdventure name: **{adventure}**"
                    ).format(
                        difficulty=num,
                        time_left=time,
                        adventure=ADVENTURE_NAMES[num],
                    ),
                    colour=self.bot.config.game.primary_colour,
                )
            )

        damage, armor = await self.bot.get_damage_armor_for(ctx.author)

        luck_booster = await self.bot.get_booster(ctx.author, "luck")
        current_level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
        luck_multiply = ctx.character_data["luck"]
        if (
            buildings := await self.bot.get_city_buildings(ctx.character_data["guild"])
        ):
            bonus = buildings["adventure_building"]
コード例 #18
0
    async def adventures(self, ctx):
        _("""Shows all adventures, their names, descriptions, and your chances to beat them in picture form.
            Your chances are determined by your equipped items, race and class bonuses, your level and your God-given luck."""
          )
        damage, defense = await self.bot.get_damage_armor_for(ctx.author)
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        luck_booster = await self.bot.get_booster(ctx.author, "luck")

        msg = await ctx.send(_("Loading images..."))

        chances = []
        for adv in self.bot.config.adventure_times:
            success = rpgtools.calcchance(
                damage,
                defense,
                adv,
                int(level),
                ctx.character_data["luck"],
                booster=luck_booster,
                returnsuccess=False,
            )
            chances.append((success[0] - success[2], success[1] + success[2]))

        async with self.bot.trusted_session.post(
                f"{self.bot.config.okapi_url}/api/genadventures",
                json={"percentages": chances},
        ) as r:
            images = await r.json()

        await msg.delete()

        files = [
            discord.File(filename=f"Adventure{idx + 1}.png",
                         fp=BytesIO(b64decode(img[22:])))
            for idx, img in enumerate(images)
        ]
        pages = [
            discord.Embed().set_image(
                url=f"attachment://Adventure{idx + 1}.png")
            for idx in range(len(images))
        ]

        await self.bot.paginator.AdventurePaginator(embeds=pages,
                                                    files=files).paginate(ctx)
コード例 #19
0
ファイル: __init__.py プロジェクト: Mr-E0us-Stranger/IdleRPG
    async def adventures(self, ctx):
        _("""A list of all adventures with success rates, name and time it takes."""
          )
        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        all_dungeons = list(self.bot.config.adventure_times.keys())
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        damage = sword["damage"] if sword else 0
        defense = shield["armor"] if shield else 0

        msg = await ctx.send(_("Loading images..."))

        chances = []
        for adv in all_dungeons:
            success = rpgtools.calcchance(
                damage,
                defense,
                adv,
                int(level),
                ctx.character_data["luck"],
                returnsuccess=False,
            )
            chances.append((success[0] - success[2], success[1] + success[2]))
        async with self.bot.trusted_session.post(
                f"{self.bot.config.okapi_url}/api/genadventures",
                json={"percentages": chances},
        ) as r:
            images = await r.json()

        await msg.delete()

        files = [
            discord.File(filename=f"Adventure{idx + 1}.png",
                         fp=BytesIO(b64decode(img[22:])))
            for idx, img in enumerate(images)
        ]
        pages = [
            discord.Embed().set_image(
                url=f"attachment://Adventure{idx + 1}.png")
            for idx in range(len(images))
        ]

        await self.bot.paginator.AdventurePaginator(embeds=pages,
                                                    files=files).paginate(ctx)
コード例 #20
0
 async def highscore(self, ctx):
     _("""The top 10 players by XP.""")
     await ctx.trigger_typing()
     players = await self.bot.pool.fetch(
         'SELECT "user", "name", "xp" from profile ORDER BY "xp" DESC LIMIT 10;'
     )
     result = ""
     for idx, profile in enumerate(players):
         username = await rpgtools.lookup(self.bot, profile["user"])
         text = _(
             "{name}, a character by `{username}` with Level **{level}** (**{xp}** XP)"
         ).format(
             name=profile["name"],
             username=username,
             level=rpgtools.xptolevel(profile["xp"]),
             xp=profile["xp"],
         )
         result = f"{result}{idx + 1}. {text}\n"
     result = discord.Embed(title=_("The Best Players"),
                            description=result,
                            colour=0xE7CA01)
     await ctx.send(embed=result)
コード例 #21
0
 async def adventure(self, ctx, dungeonnumber: IntFromTo(1, 20)):
     _("""Sends your character on an adventure.""")
     if dungeonnumber > int(rpgtools.xptolevel(ctx.character_data["xp"])):
         return await ctx.send(
             _("You must be on level **{level}** to do this adventure.").
             format(level=dungeonnumber))
     time_booster = await self.bot.get_booster(ctx.author, "time")
     time = self.bot.config.adventure_times[dungeonnumber]
     if time_booster:
         time = time / 2
     # Silver = -5%, Gold = -10%, Emerald = -25%
     # TODO: Maybe make a func to get the actual rank
     if await user_is_patron(self.bot,
                             ctx.author):  # save calls for normal people :)
         if await user_is_patron(self.bot, ctx.author, "Emerald Donators"):
             time = time * 0.75
         elif await user_is_patron(self.bot, ctx.author, "Gold Donators"):
             time = time * 0.9
         elif await user_is_patron(self.bot, ctx.author, "Silver Donators"):
             time = time * 0.95
     await self.bot.start_adventure(ctx.author, dungeonnumber, time)
     await ctx.send(
         _("Successfully sent your character out on an adventure. Use `{prefix}status` to see the current status of the mission."
           ).format(prefix=ctx.prefix))
コード例 #22
0
ファイル: __init__.py プロジェクト: indij/IdleRPG
    async def _class(self, ctx):
        _(
            """Change or select your primary or secondary class.

            - Warriors gain added defense
            - Thieves gain access to `{prefix}steal`
            - Mages gain added damage
            - Rangers gain access to a pet which can hunt for gear items
            - Raiders gain additional raidstats, used in raidbattles and raids
            - Ritualists gain additional favor from sacrificing items and are twice as likely to receive loot from adventures
            (- Paragons gain added damage *and* defense; the class is only available to donators)

            The second class unlocks at level 12. Selecting a class the first time is free (No Class -> Class), but changing it later will cost $5,000 (Class -> another Class)

            (This command has a cooldown of 24 hours)"""
        )
        if rpgtools.xptolevel(ctx.character_data["xp"]) >= 12:
            val = await self.bot.paginator.Choose(
                title=_("Select class to change"),
                entries=[_("Primary Class"), _("Secondary Class")],
                return_index=True,
            ).paginate(ctx)
        else:
            val = 0
        embeds = [
            discord.Embed(
                title=_("Warrior"),
                description=_(
                    "The tank class. Charge into battle with additional defense!\n+1"
                    " defense per evolution."
                ),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Thief"),
                description=_(
                    # xgettext: no-python-format
                    "The sneaky money stealer...\nGet access to `{prefix}steal` to"
                    " steal 10% of a random player's money, if successful.\n+8% success"
                    " chance per evolution."
                ).format(prefix=ctx.prefix),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Mage"),
                description=_(
                    "Utilise powerful magic for stronger attacks.\n+1 damage per"
                    " evolution."
                ),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Ranger"),
                description=_(
                    "Item hunter and trainer of their very own pet.\nGet access to"
                    " `{prefix}pet` to interact with your pet and let it get items for"
                    " you.\n+3 minimum stat and +6 maximum stat per evolution."
                ).format(prefix=ctx.prefix),
                colour=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Raider"),
                description=_(
                    "A strong warrior who gives their life for the fight against"
                    " Zerekiel.\nEvery evolution boosts your raidstats by an additional"
                    " 10%."
                ),
                colour=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Ritualist"),
                description=_(
                    "A seer, a sacrificer and a follower.\nThe Ritualist devotes their"
                    " life to the god they follow. For every evolution, their"
                    " sacrifices are 5% more effective. They have twice the chance to"
                    " get loot from adventures."
                ),
                colour=self.bot.config.primary_colour,
            ),
        ]
        choices = ["Warrior", "Thief", "Mage", "Ranger", "Raider", "Ritualist"]
        if await user_is_patron(self.bot, ctx.author):
            embeds.append(
                discord.Embed(
                    title=_("Paragon"),
                    description=_(
                        "Absorb the appreciation of the devs into your soul to power"
                        " up.\n+1 damage and defense per evolution."
                    ),
                    color=self.bot.config.primary_colour,
                )
            )
            choices.append("Paragon")
        lines = [
            self.bot.get_class_line(class_) for class_ in ctx.character_data["class"]
        ]
        for line in lines:
            for e in embeds:
                if _(line) == e.title:
                    embeds.remove(e)
            try:
                choices.remove(line)
            except ValueError:
                pass
        profession = await self.bot.paginator.ChoosePaginator(
            extras=embeds, choices=choices
        ).paginate(ctx)
        profession_ = self.bot.config.classes[profession][0]
        new_classes = copy(ctx.character_data["class"])
        new_classes[val] = profession_
        if not await ctx.confirm(
            _(
                "You are about to select the `{profession}` class for yourself."
                " {textaddon} Proceed?"
            ).format(
                textaddon=_(
                    "This **costs nothing**, but changing it later will cost **$5000**."
                )
                if ctx.character_data["class"][val] == "No Class"
                else _("This will cost **$5000**."),
                profession=profession,
            )
        ):
            return await ctx.send(_("Class selection cancelled."))
        if ctx.character_data["class"][val] == "No Class":
            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "class"=$1 WHERE "user"=$2;',
                    new_classes,
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_abs(
                    ctx.author.id, class_=new_classes
                )
                if profession == "Ranger":
                    await conn.execute(
                        'INSERT INTO pets ("user") VALUES ($1);', ctx.author.id
                    )
            await ctx.send(
                _("Your new class is now `{profession}`.").format(
                    profession=_(profession)
                )
            )
        else:
            if not await self.bot.has_money(ctx.author.id, 5000):
                await self.bot.reset_cooldown(ctx)
                return await ctx.send(
                    _("You're too poor for a class change, it costs **$5000**.")
                )

            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "class"=$1, "money"="money"-$2 WHERE'
                    ' "user"=$3;',
                    new_classes,
                    5000,
                    ctx.author.id,
                )
                await self.bot.cache.update_profile_cols_rel(
                    ctx.author.id, class_=new_classes, money=-5000
                )
                await conn.execute('DELETE FROM pets WHERE "user"=$1;', ctx.author.id)
                if profession == "Ranger":
                    await conn.execute(
                        'INSERT INTO pets ("user") VALUES ($1);', ctx.author.id
                    )
                await self.bot.log_transaction(
                    ctx,
                    from_=ctx.author.id,
                    to=2,
                    subject="money",
                    data={"Amount": 5000},
                    conn=conn,
                )
            await ctx.send(
                _(
                    "You selected the class `{profession}`. **$5000** was taken off"
                    " your balance."
                ).format(profession=_(profession))
            )
コード例 #23
0
ファイル: __init__.py プロジェクト: ctcusick/IdleRPG
                            "You don't own any loot items with the IDs: {itemids}"
                        ).format(
                            itemids=", ".join([str(loot_id) for loot_id in loot_ids])
                        )
                    )
        reward = await self.bot.paginator.Choose(
            title=_("Select a reward for the {amount} items".format(amount=count)),
            footer=_("Do you want favor? {prefix}sacrifice instead").format(
                prefix=ctx.prefix
            ),
            return_index=True,
            entries=[f"**${value}**", _("**{value} XP**").format(value=value // 4)],
        ).paginate(ctx)
        reward = ["money", "xp"][reward]
        if reward == "xp":
            old_level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
            value = value // 4

        async with self.bot.pool.acquire() as conn:
            if len(loot_ids) == 0:
                await conn.execute('DELETE FROM loot WHERE "user"=$1;', ctx.author.id)
            else:
                await conn.execute(
                    'DELETE FROM loot WHERE "id"=ANY($1) AND "user"=$2;',
                    loot_ids,
                    ctx.author.id,
                )
            await conn.execute(
                f'UPDATE profile SET "{reward}"="{reward}"+$1 WHERE "user"=$2;',
                value,
                ctx.author.id,
コード例 #24
0
                subject="adventure",
                data={
                    "Gold": gold,
                    "Item":
                    item["name"],  # compare against loot names if necessary
                    "Value": item["value"],
                },
            )

            # TODO: Embeds ftw
            await ctx.send(
                _("You have completed your adventure and received **${gold}** as well"
                  " as a new item: **{item}**. Experience gained: **{xp}**.").
                format(gold=gold, item=item["name"], xp=xp))

            new_level = int(rpgtools.xptolevel(ctx.character_data["xp"] + xp))

            if current_level != new_level:
                await self.bot.process_levelup(ctx, new_level, current_level)

    @has_char()
    @has_adventure()
    @commands.command(brief=_("Cancels your current adventure."))
    @locale_doc
    async def cancel(self, ctx):
        _("""Cancels your ongoing adventure and allows you to start a new one right away. You will not receive any rewards if you cancel your adventure."""
          )
        if not await ctx.confirm(
                _("Are you sure you want to cancel your current adventure?")):
            return await ctx.send(
                _("Did not cancel your adventure. The journey continues..."))
コード例 #25
0
ファイル: __init__.py プロジェクト: Mr-E0us-Stranger/IdleRPG
    async def _class(self, ctx):
        _("""Change your primary or secondary class.""")
        if int(rpgtools.xptolevel(ctx.character_data["xp"])) >= 12:
            val = await self.bot.paginator.Choose(
                title=_("Select class to change"),
                entries=[_("Primary Class"),
                         _("Secondary Class")],
                return_index=True,
            ).paginate(ctx)
        else:
            val = 0
        embeds = [
            discord.Embed(
                title=_("Warrior"),
                description=
                _("The tank class. Charge into battle with additional defense!\n+1 defense per evolution."
                  ),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Thief"),
                description=_(
                    # xgettext: no-python-format
                    "The sneaky money stealer...\nGet access to `{prefix}steal` to steal 10% of the target's money, if successful.\n+8% success chance per evolution."
                ).format(prefix=ctx.prefix),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Mage"),
                description=
                _("Utilise powerful magic for stronger attacks.\n+1 damage per evolution."
                  ),
                color=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Ranger"),
                description=
                _("Item hunter and trainer of their very own pet.\nGet access to `{prefix}pet` to interact with your pet and let it get items for you.\n+3 minimum stat and +6 maximum stat per evolution."
                  ).format(prefix=ctx.prefix),
                colour=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Raider"),
                description=
                _("A strong warrior who gives their life for the fight against Zerekiel.\nEvery evolution boosts your raidstats by an additional 10%."
                  ),
                colour=self.bot.config.primary_colour,
            ),
            discord.Embed(
                title=_("Ritualist"),
                description=
                _("A seer, a sacrificer and a follower.\nThe Ritualist devotes their life to the god they follow. For every evolution, their sacrifices are 5% more effective. They have twice the chance to get loot from adventures."
                  ),
                colour=self.bot.config.primary_colour,
            ),
        ]
        choices = ["Warrior", "Thief", "Mage", "Ranger", "Raider", "Ritualist"]
        if await user_is_patron(self.bot, ctx.author):
            embeds.append(
                discord.Embed(
                    title=_("Paragon"),
                    description=
                    _("Absorb the appreciation of the devs into your soul to power up.\n+1 damage and defense per evolution."
                      ),
                    color=self.bot.config.primary_colour,
                ))
            choices.append("Paragon")
        lines = [
            self.bot.get_class_line(class_)
            for class_ in ctx.character_data["class"]
        ]
        for line in lines:
            for e in embeds:
                if _(line) == e.title:
                    embeds.remove(e)
            try:
                choices.remove(line)
            except ValueError:
                pass
        profession = await self.bot.paginator.ChoosePaginator(
            extras=embeds, choices=choices).paginate(ctx)
        profession_ = self.bot.config.classes[profession][0]
        new_classes = copy(ctx.character_data["class"])
        new_classes[val] = profession_
        if not await ctx.confirm(
                _("You are about to select the `{profession}` class for yourself. {textaddon} Proceed?"
                  ).
                format(
                    textaddon=
                    _("This **costs nothing**, but changing it later will cost **$5000**."
                      ) if ctx.character_data["class"][val] == "No Class" else
                    _("This will cost **$5000**."),
                    profession=profession,
                )):
            return await ctx.send(_("Class selection cancelled."))
        if ctx.character_data["class"][val] == "No Class":
            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "class"=$1 WHERE "user"=$2;',
                    new_classes,
                    ctx.author.id,
                )
                if profession == "Ranger":
                    await conn.execute(
                        'INSERT INTO pets ("user") VALUES ($1);',
                        ctx.author.id)
            await ctx.send(
                _("Your new class is now `{profession}`.").format(
                    profession=_(profession)))
        else:
            if not await self.bot.has_money(ctx.author.id, 5000):
                await self.bot.reset_cooldown(ctx)
                return await ctx.send(
                    _("You're too poor for a class change, it costs **$5000**."
                      ))

            async with self.bot.pool.acquire() as conn:
                await conn.execute(
                    'UPDATE profile SET "class"=$1, "money"="money"-$2 WHERE "user"=$3;',
                    new_classes,
                    5000,
                    ctx.author.id,
                )
                await conn.execute('DELETE FROM pets WHERE "user"=$1;',
                                   ctx.author.id)
                if profession == "Ranger":
                    await conn.execute(
                        'INSERT INTO pets ("user") VALUES ($1);',
                        ctx.author.id)
            await ctx.send(
                _("You selected the class `{profession}`. **$5000** was taken off your balance."
                  ).format(profession=_(profession)))
コード例 #26
0
ファイル: __init__.py プロジェクト: ctcusick/IdleRPG
    async def profile(self, ctx, *, person: User = Author):
        _("""View someone's or your own profile.""")
        await ctx.trigger_typing()
        targetid = person.id
        async with self.bot.pool.acquire() as conn:
            profile = await conn.fetchrow(
                'SELECT * FROM profile WHERE "user"=$1;', targetid
            )
            if not profile:
                return await ctx.send(
                    _("**{person}** does not have a character.").format(person=person)
                )
            items = await self.bot.get_equipped_items_for(targetid)
            mission = await self.bot.get_adventure(targetid)
            guild = await conn.fetchval(
                'SELECT name FROM guild WHERE "id"=$1;', profile["guild"]
            )
            v1 = sum(i["damage"] for i in items)
            v2 = sum(i["armor"] for i in items)
            damage, armor = await self.bot.generate_stats(
                targetid, v1, v2, classes=profile["class"], race=profile["race"]
            )
            extras = (damage - v1, armor - v2)
            sworddmg = f"{v1}{' (+' + str(extras[0]) + ')' if extras[0] else ''}"
            shielddef = f"{v2}{' (+' + str(extras[1]) + ')' if extras[1] else ''}"

            right_hand = "None Equipped"
            left_hand = "None Equipped"

            any_count = sum(1 for i in items if i["hand"] == "any")
            if len(items) == 2 and any_count == 1 and items[0]["hand"] == "any":
                items = [items[1], items[0]]

            for i in items:
                if i["hand"] == "both":
                    right_hand, left_hand = i["name"], i["name"]
                elif i["hand"] == "left":
                    left_hand = i["name"]
                elif i["hand"] == "right":
                    right_hand = i["name"]
                elif i["hand"] == "any":
                    if right_hand == "None Equipped":
                        right_hand = i["name"]
                    else:
                        left_hand = i["name"]

            url = f"{self.bot.config.okapi_url}/api/genprofile"
            async with self.bot.trusted_session.post(
                url,
                data={
                    "name": profile["name"],
                    "color": profile["colour"],
                    "image": profile["background"],
                    "race": profile["race"],
                    "classes": profile["class"],
                    "damage": sworddmg,
                    "defense": shielddef,
                    "swordName": right_hand,
                    "shieldName": left_hand,
                    "level": rpgtools.xptolevel(profile["xp"]),
                    "money": f"{profile['money']}",
                    "pvpWins": f"{profile['pvpwins']}",
                    "marriage": i
                    if (
                        i := await rpgtools.lookup(
                            self.bot, profile["marriage"], return_none=True
                        )
                    )
                    else _("Not Married"),
                    "guild": guild or _("No Guild"),
                    "god": profile["god"] or _("No God"),
                    "icons": [
                        self.bot.get_class_line(c).lower() for c in profile["class"]
                    ],
                    "adventure": f"Adventure {mission[0]}\n{mission[1] if not mission[2] else _('Finished')}"
                    if mission
                    else _("No Mission"),
                },
            ) as req:
                img = BytesIO(await req.read())
コード例 #27
0
ファイル: adventure.py プロジェクト: terror-kvothe/IdleRPG
    async def status(self, ctx):
        _("""Checks your adventure status.""")
        num, time, done = ctx.adventure_data

        if not done:
            return await ctx.send(
                _("""\
You are currently on an adventure with difficulty `{difficulty}`.
Time until it completes: `{time_left}`
Adventure name: `{adventure}`""").format(
                    difficulty=num,
                    time_left=time,
                    adventure=self.bot.config.adventure_names[num],
                ))

        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        sword, shield = await self.bot.generate_stats(
            ctx.author,
            sword["damage"] if sword else 0,
            shield["armor"] if shield else 0,
            classes=ctx.character_data["class"],
            race=ctx.character_data["race"],
        )

        luck_booster = await self.bot.get_booster(ctx.author, "luck")
        current_level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
        luck_multiply = ctx.character_data["luck"]
        success = rpgtools.calcchance(
            sword,
            shield,
            num,
            current_level,
            luck_multiply,
            returnsuccess=True,
            booster=bool(luck_booster),
        )
        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)
            return await ctx.send(_("You died on your mission. Try again!"))

        gold = round(
            random.randint(20 * (num - 1) or 1, 60 * (num - 1) or 70) *
            luck_multiply)

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

        xp = random.randint(250 * num, 500 * num)

        async with self.bot.pool.acquire() as conn:

            if random.randint(1, 10) < 10:
                minstat = round(num * luck_multiply)
                maxstat = round(5 + int(num * 1.5) * luck_multiply)
                item = await self.bot.create_random_item(
                    minstat=minstat if minstat < 35 else 35,
                    maxstat=maxstat if maxstat < 35 else 35,
                    minvalue=round(num * luck_multiply),
                    maxvalue=round(num * 50 * luck_multiply),
                    owner=ctx.author,
                )
            else:
                item = items.get_item()
                await conn.execute(
                    'INSERT INTO loot ("name", "value", "user") VALUES ($1, $2, $3);',
                    item["name"],
                    item["value"],
                    ctx.author.id,
                )

            if (guild := ctx.character_data["guild"]):
                await conn.execute(
                    'UPDATE guild SET "money"="money"+$1 WHERE "id"=$2;',
                    int(gold / 10),
                    guild,
                )

            await conn.execute(
                'UPDATE profile SET "money"="money"+$1, "xp"="xp"+$2, "completed"="completed"+1 WHERE "user"=$3;',
                gold,
                xp,
                ctx.author.id,
            )

            if (partner := ctx.character_data["marriage"]):
                await conn.execute(
                    'UPDATE profile SET "money"="money"+($1*(1+"lovescore"/1000000)) WHERE "user"=$2;',
                    int(gold / 2),
                    partner,
                )
コード例 #28
0
ファイル: adventure.py プロジェクト: terror-kvothe/IdleRPG
class Adventure(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @has_char()
    @commands.command(aliases=["missions", "dungeons"])
    @locale_doc
    async def adventures(self, ctx):
        _("""A list of all adventures with success rates, name and time it takes."""
          )
        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        all_dungeons = list(self.bot.config.adventure_times.keys())
        level = rpgtools.xptolevel(ctx.character_data["xp"])
        damage = sword["damage"] if sword else 0
        defense = shield["armor"] if shield else 0

        msg = await ctx.send(_("Loading images..."))

        chances = []
        for adv in all_dungeons:
            success = rpgtools.calcchance(
                damage,
                defense,
                adv,
                int(level),
                ctx.character_data["luck"],
                returnsuccess=False,
            )
            chances.append((success[0] - success[2], success[1] + success[2]))
        thing = functools.partial(rpgtools.makeadventures, chances)
        images = await self.bot.loop.run_in_executor(None, thing)

        await msg.delete()

        files = [
            discord.File(img, filename=f"Adventure{idx + 1}.png")
            for idx, img in enumerate(images)
        ]
        pages = [
            discord.Embed().set_image(
                url=f"attachment://Adventure{idx + 1}.png")
            for idx in range(len(images))
        ]

        await self.bot.paginator.AdventurePaginator(embeds=pages,
                                                    files=files).paginate(ctx)

    @has_char()
    @has_no_adventure()
    @commands.command(aliases=["mission", "a", "dungeon"])
    @locale_doc
    async def adventure(self, ctx, dungeonnumber: IntFromTo(1, 20)):
        _("""Sends your character on an adventure.""")
        if dungeonnumber > int(rpgtools.xptolevel(ctx.character_data["xp"])):
            return await ctx.send(
                _("You must be on level **{level}** to do this adventure.").
                format(level=dungeonnumber))
        time_booster = await self.bot.get_booster(ctx.author, "time")
        time = self.bot.config.adventure_times[dungeonnumber]
        if time_booster:
            time = time / 2
        await self.bot.start_adventure(ctx.author, dungeonnumber, time)
        await ctx.send(
            _("Successfully sent your character out on an adventure. Use `{prefix}status` to see the current status of the mission."
              ).format(prefix=ctx.prefix))

    @has_char()
    @has_no_adventure()
    @user_cooldown(7200)
    @commands.command()
    @locale_doc
    async def activeadventure(self, ctx):
        _("""Go out on a docile adventure controlled by reactions.""")
        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

        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        attack, defense = await self.bot.generate_stats(
            ctx.author,
            float(sword["damage"] if sword else 0),
            float(shield["armor"] if shield else 0),
        )

        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(r, u):
                return (u == ctx.author and r.message.id == msg.id
                        and direction_emojis_inverse.get(str(r.emoji),
                                                         None) in possible)

            r, u = await self.bot.wait_for("reaction_add",
                                           check=check,
                                           timeout=30)

            return direction_emojis_inverse[str(r.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)
                await self.bot.pool.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                await ctx.send(
                    _("You found a treasure with **${money}** inside!").format(
                        money=money))
                cell.treasure = False
            elif cell.enemy:

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

                def is_valid_move(r, u):
                    return (r.message.id == msg.id and u == ctx.author
                            and str(r.emoji) in emojis)

                emojis = {
                    "\U00002694": "attack",
                    "\U0001f6e1": "defend",
                    "\U00002764": "recover",
                }
                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}
```""")

                    r, u = await self.bot.wait_for("reaction_add",
                                                   check=is_valid_move,
                                                   timeout=30)

                    try:
                        await msg.remove_reaction(r, u)
                    except discord.Forbidden:
                        pass

                    enemy_move = random.choice(["attack", "defend", "recover"])
                    player_move = emojis[str(r.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)
        await self.bot.pool.execute(
            'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
            money,
            ctx.author.id,
        )

        await ctx.send(
            _("You have reached the exit and were rewarded **${money}** for getting out!"
              ).format(money=money))

    @has_char()
    @has_adventure()
    @commands.command(aliases=["s"])
    @locale_doc
    async def status(self, ctx):
        _("""Checks your adventure status.""")
        num, time, done = ctx.adventure_data

        if not done:
            return await ctx.send(
                _("""\
You are currently on an adventure with difficulty `{difficulty}`.
Time until it completes: `{time_left}`
Adventure name: `{adventure}`""").format(
                    difficulty=num,
                    time_left=time,
                    adventure=self.bot.config.adventure_names[num],
                ))

        sword, shield = await self.bot.get_equipped_items_for(ctx.author)
        sword, shield = await self.bot.generate_stats(
            ctx.author,
            sword["damage"] if sword else 0,
            shield["armor"] if shield else 0,
            classes=ctx.character_data["class"],
            race=ctx.character_data["race"],
        )

        luck_booster = await self.bot.get_booster(ctx.author, "luck")
        current_level = int(rpgtools.xptolevel(ctx.character_data["xp"]))
        luck_multiply = ctx.character_data["luck"]
        success = rpgtools.calcchance(
            sword,
            shield,
            num,
            current_level,
            luck_multiply,
            returnsuccess=True,
            booster=bool(luck_booster),
        )
        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)
            return await ctx.send(_("You died on your mission. Try again!"))

        gold = round(
            random.randint(20 * (num - 1) or 1, 60 * (num - 1) or 70) *
            luck_multiply)

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

        xp = random.randint(250 * num, 500 * num)

        async with self.bot.pool.acquire() as conn:

            if random.randint(1, 10) < 10:
                minstat = round(num * luck_multiply)
                maxstat = round(5 + int(num * 1.5) * luck_multiply)
                item = await self.bot.create_random_item(
                    minstat=minstat if minstat < 35 else 35,
                    maxstat=maxstat if maxstat < 35 else 35,
                    minvalue=round(num * luck_multiply),
                    maxvalue=round(num * 50 * luck_multiply),
                    owner=ctx.author,
                )
            else:
                item = items.get_item()
                await conn.execute(
                    'INSERT INTO loot ("name", "value", "user") VALUES ($1, $2, $3);',
                    item["name"],
                    item["value"],
                    ctx.author.id,
                )

            if (guild := ctx.character_data["guild"]):
                await conn.execute(
                    'UPDATE guild SET "money"="money"+$1 WHERE "id"=$2;',
                    int(gold / 10),
                    guild,
                )

            await conn.execute(
                'UPDATE profile SET "money"="money"+$1, "xp"="xp"+$2, "completed"="completed"+1 WHERE "user"=$3;',
                gold,
                xp,
                ctx.author.id,
            )

            if (partner := ctx.character_data["marriage"]):
                await conn.execute(
                    'UPDATE profile SET "money"="money"+($1*(1+"lovescore"/1000000)) WHERE "user"=$2;',
                    int(gold / 2),
                    partner,
                )

            await ctx.send(
                _("You have completed your adventure and received **${gold}** as well as a new item: **{item}**. Experience gained: **{xp}**."
                  ).format(gold=gold, item=item["name"], xp=xp))

            new_level = int(rpgtools.xptolevel(ctx.character_data["xp"] + xp))

            if current_level == new_level:
                return

            if (reward := random.choice(["crates", "money",
                                         "item"])) == "crates":
                if new_level < 6:
                    column = "crates_common"
                    amount = new_level
                    reward_text = f"**{amount}** <:CrateCommon:598094865666015232>"
                elif new_level < 10:
                    column = "crates_uncommon"
                    amount = round(new_level / 2)
                    reward_text = f"**{amount}** <:CrateUncommon:598094865397579797>"
                elif new_level < 15:
                    column = "crates_rare"
                    amount = 2
                    reward_text = "**2** <:CrateRare:598094865485791233>"
                elif new_level < 20:
                    column = "crates_rare"
                    amount = 3
                    reward_text = "**3** <:CrateRare:598094865485791233>"
                else:
                    column = "crates_magic"
                    amount = 1
                    reward_text = "**1** <:CrateMagic:598094865611358209>"
                await self.bot.pool.execute(
                    f'UPDATE profile SET {column}={column}+$1 WHERE "user"=$2;',
                    amount,
                    ctx.author.id,
                )
コード例 #29
0
ファイル: __init__.py プロジェクト: ctcusick/IdleRPG
    async def profile2(self, ctx, *, target: User = Author):
        _("""View someone's profile, not image based.""")
        rank_money, rank_xp = await self.bot.get_ranks_for(target)

        items = await self.bot.get_equipped_items_for(target)
        async with self.bot.pool.acquire() as conn:
            p_data = await conn.fetchrow(
                'SELECT * FROM profile WHERE "user"=$1;', target.id
            )
            if not p_data:
                return await ctx.send(
                    _("**{target}** does not have a character.").format(target=target)
                )
            mission = await self.bot.get_adventure(target)
            guild = await conn.fetchval(
                'SELECT name FROM guild WHERE "id"=$1;', p_data["guild"]
            )
        try:
            colour = discord.Colour.from_rgb(*rpgtools.hex_to_rgb(p_data["colour"]))
        except ValueError:
            colour = 0x000000
        if mission:
            timeleft = str(mission[1]).split(".")[0] if not mission[2] else "Finished"

        right_hand = None
        left_hand = None

        any_count = sum(1 for i in items if i["hand"] == "any")
        if len(items) == 2 and any_count == 1 and items[0]["hand"] == "any":
            items = [items[1], items[0]]

        for i in items:
            if i["hand"] == "both":
                right_hand, left_hand = i, i
            elif i["hand"] == "left":
                left_hand = i
            elif i["hand"] == "right":
                right_hand = i
            elif i["hand"] == "any":
                if right_hand is None:
                    right_hand = i
                else:
                    left_hand = i

        right_hand = (
            f"{right_hand['name']} - {right_hand['damage'] + right_hand['armor']}"
            if right_hand
            else _("None Equipped")
        )
        left_hand = (
            f"{left_hand['name']} - {left_hand['damage'] + left_hand['armor']}"
            if left_hand
            else _("None Equipped")
        )
        level = rpgtools.xptolevel(p_data["xp"])
        em = discord.Embed(colour=colour, title=f"{target}: {p_data['name']}")
        em.set_thumbnail(url=target.avatar_url)
        em.add_field(
            name=_("General"),
            value=_(
                """\
**Money**: `${money}`
**Level**: `{level}`
**Class**: `{class_}`
**Race**: `{race}`
**PvP Wins**: `{pvp}`
**Guild**: `{guild}`"""
            ).format(
                money=p_data["money"],
                level=level,
                class_="/".join(p_data["class"]),
                race=p_data["race"],
                pvp=p_data["pvpwins"],
                guild=guild,
            ),
        )
        em.add_field(
            name=_("Ranks"),
            value=_("**Richest**: `{rank_money}`\n**XP**: `{rank_xp}`").format(
                rank_money=rank_money, rank_xp=rank_xp
            ),
        )
        em.add_field(
            name=_("Equipment"),
            value=_("Right Hand: {right_hand}\nLeft Hand: {left_hand}").format(
                right_hand=right_hand, left_hand=left_hand
            ),
        )
        if mission:
            em.add_field(name=_("Mission"), value=f"{mission[0]} - {timeleft}")
        await ctx.send(embed=em)
コード例 #30
0
    async def adventure(self, ctx):
        _("""Starts a guild adventure.""")
        if await self.bot.get_guild_adventure(ctx.character_data["guild"]):
            await self.bot.reset_guild_cooldown(ctx)
            return await ctx.send(
                _(
                    "Your guild is already on an adventure! Use `{prefix}guild status` to view how long it still lasts."
                ).format(prefix=ctx.prefix)
            )
        guild = await self.bot.pool.fetchrow(
            'SELECT * FROM guild WHERE "id"=$1;', ctx.character_data["guild"]
        )

        msg = await ctx.send(
            _(
                "{author} seeks a guild adventure for **{guild}**! React to join! Unlimited players can join in the next minute. The minimum of players required is 3."
            ).format(author=ctx.author.mention, guild=guild["name"])
        )

        await msg.add_reaction("\U00002694")

        joined = [ctx.author]
        difficulty = int(rpgtools.xptolevel(ctx.character_data["xp"]))
        started = False

        def apply(r, u):
            return (
                r.message.id == msg.id
                and str(r.emoji) == "\U00002694"
                and u not in joined
                and not u.bot
            )

        while not started:
            try:
                r, u = await self.bot.wait_for("reaction_add", check=apply, timeout=30)
                user = await self.bot.pool.fetchrow(
                    'SELECT guild, xp FROM profile WHERE "user"=$1;', u.id
                )
                if user and user["guild"] == guild["id"]:
                    difficulty += int(rpgtools.xptolevel(user["xp"]))
                    joined.append(u)
                    await ctx.send(
                        _("Alright, {user}, you have been added.").format(
                            user=u.mention
                        )
                    )
                else:
                    await ctx.send(_("You aren't in their guild."))
            except asyncio.TimeoutError:
                if len(joined) < 3:
                    return await ctx.send(
                        _(
                            "You didn't get enough other players for the guild adventure."
                        )
                    )
                started = True

        time = timedelta(hours=difficulty * 0.5)

        await self.bot.start_guild_adventure(guild["id"], difficulty, time)

        await ctx.send(
            _(
                """
Guild adventure for **{guild}** started!
Participants:
{participants}

Difficulty is **{difficulty}**
Time it will take: **{time}**
"""
            ).format(
                guild=guild["name"],
                participants=", ".join([m.mention for m in joined]),
                difficulty=difficulty,
                time=time,
            )
        )