Skip to content

Commit

Permalink
Add collective updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
scragly committed Dec 30, 2021
1 parent 5a69d4e commit b49b2c3
Show file tree
Hide file tree
Showing 25 changed files with 1,972 additions and 405 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ verify_ssl = true
[dev-packages]
better-exceptions = "*"
pipenv-to-requirements = "*"
pillow-simd = "*"

[packages]
"discord.py" = "~=1.6.0"
Expand All @@ -15,6 +14,7 @@ pendulum = "~=2.1.2"
everstone = "*"
rapidfuzz = "*"
afkarena = "*"
pillow-simd = "*"

[requires]
python_version = "3.9"
Expand Down
422 changes: 246 additions & 176 deletions Pipfile.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions dreaf/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import pathlib
import sys
from logging import handlers
Expand All @@ -18,11 +19,11 @@
__all__ = ('ctx',)

pendulum.set_local_timezone()
debug_flag = True
debug_flag = bool(os.environ.get("DEBUG", False))

logging.getLogger().setLevel(logging.DEBUG)
discord_log = logging.getLogger("discord")
discord_log.setLevel(logging.INFO)
discord_log.setLevel(logging.DEBUG if debug_flag else logging.INFO)
dreaf_log = logging.getLogger("dreaf")

# setup log directory
Expand Down
10 changes: 2 additions & 8 deletions dreaf/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@

bot = DreafBot()


@bot.check
async def only_dev(ctx):
return ctx.author.id == 174764205927432192


bot.load_extension("dreaf.testing")
# bot.load_extension("dreaf.giftcodes")
# bot.load_extension("dreaf.players")
# bot.load_extension("dreaf.afk_events")
# bot.load_extension("dreaf.items")
# bot.load_extension("dreaf.reddit")
# bot.load_extension("dreaf.hero_img")
bot.load_extension("dreaf.reddit")
bot.load_extension("dreaf.commands.hero_images")

bot.run()
2 changes: 2 additions & 0 deletions dreaf/bot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import typing as t

import aiohttp
import discord
from discord.ext import commands
from discord.ext import context
Expand All @@ -19,6 +20,7 @@ def __init__(self):
self._global_reaction_triggers: t.Dict[str, t.Callable] = {
constants.EMOJI_DELETE: self._delete_trigger,
}
self.http_session = aiohttp.ClientSession()

def run(self):
super().run(constants.TOKEN)
Expand Down
15 changes: 10 additions & 5 deletions dreaf/checks.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import typing as t

import discord
from discord.ext import commands

if t.TYPE_CHECKING:
from .bot import DreafBot

def _ensure_member(ctx) -> t.Optional[discord.Member]:
return ctx.author if ctx.guild else ctx.bot.guild.get_member(ctx.author.id)


def is_owner():
Expand All @@ -14,17 +16,20 @@ async def predicate(ctx):

def is_master():
async def predicate(ctx):
return ctx.bot.is_master(ctx.author)
author = _ensure_member(ctx)
return ctx.bot.is_master(author) if author else False
return commands.check(predicate)


def is_deputy():
async def predicate(ctx):
return ctx.bot.is_deputy(ctx.author)
author = _ensure_member(ctx)
return ctx.bot.is_deputy(author) if author else False
return commands.check(predicate)


def is_exemplar():
async def predicate(ctx):
return ctx.bot.is_exemplar(ctx.author)
author = _ensure_member(ctx)
return ctx.bot.is_exemplar(author) if author else False
return commands.check(predicate)
81 changes: 62 additions & 19 deletions dreaf/commands/hero_images.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
from __future__ import annotations

import io
import logging
import random
import shutil
import typing as t
from collections import Counter
from pathlib import Path

import discord
from discord.ext import commands
from discord.ext.commands import MissingRequiredArgument, converter
from PIL import Image
from discord.ext import commands

from dreaf.game.heroes import Ascension, Hero, HeroTier
from dreaf import checks
from dreaf.game.heroes import Ascension, Hero, HeroTier, Faction

if t.TYPE_CHECKING:
from dreaf.bot import DreafBot


log = logging.getLogger(__name__)


class UnknownFaction:
name = "unknown"
emblem_cap = None
Expand Down Expand Up @@ -55,7 +63,7 @@ def img_to_file(img_data, *, name="image") -> discord.File:
async def hero(self, ctx: commands.Context, hero: Hero, ascension: Ascension = None):
await ctx.send(file=self.img_to_file(hero.img_tile(ascension), name="hero.png"))

@hero.command(name="composition", aliases=["comp", "team"])
@hero.group(name="composition", aliases=["comp", "team"], invoke_without_command=True)
async def hero_comp(self, ctx: commands.Context, *heroes: Hero):
if not heroes:
return
Expand All @@ -75,6 +83,30 @@ async def hero_comp(self, ctx: commands.Context, *heroes: Hero):
x_offset += im.size[0] + 10
await ctx.send(file=self.img_to_file(img, name="comp"))

@hero_comp.command(name="noasc")
async def hero_nonecomp(self, ctx: commands.Context, *heroes: Hero):
if not heroes:
return

if len(heroes) > 5:
await ctx.send("Teams can only have a maximum of 5 heroes.")
return

images = [hero.copy(Ascension.none()).img_tile() for hero in heroes if hero]
widths, heights = zip(*(i.size for i in images))
total_width = sum(widths) + ((len(images) - 1) * 10)
max_height = max(heights)
img = Image.new('RGBA', (total_width, max_height))
x_offset = 0
for im in images:
img.paste(im, (x_offset, 0))
x_offset += im.size[0] + 10
await ctx.send(file=self.img_to_file(img, name="comp"))

@hero_comp.error
async def comp_error(self, ctx, error):
raise error

@hero.command(name="info")
async def hero_info(self, ctx: commands.Context, hero: Hero):
info = [f"Tier: {hero.tier.name}", f"Type: {hero.type.name}"]
Expand All @@ -93,26 +125,28 @@ async def hero_info(self, ctx: commands.Context, hero: Hero):

def pull_hero(self, user_id: int) -> Hero:
self.pull_counter[user_id] += 1
if self.pull_counter[user_id] >= 30:
tier = HeroTier.get("ascended")
is_celepogean = random.choices([True, False], weights=[1, 500], k=1)[0]
if is_celepogean:
factions = Faction.celepogeans()
hero = random.choice([*Hero.get_faction_heroes(*factions)])
else:
tier = random.choices(
[HeroTier.get("common"), HeroTier.get("legendary"), HeroTier.get("ascended")],
weights=[5169, 4370, 461],
)[0]

if tier.name == HeroTier.get("ascended").name:
self.pull_counter[user_id] = 0
is_celehypo = random.choices([True, False], weights=[20, 441])[0]
if is_celehypo:
heroes = Hero.get_by_tier(tier, cele=True, hypo=True, std=False)
if self.pull_counter[user_id] >= 30:
tier = HeroTier.get("Ascended")
else:
heroes = Hero.get_by_tier(tier)

else:
heroes = Hero.get_by_tier(tier)
tier = random.choices(
[
HeroTier.get("common"),
HeroTier.get("legendary"),
HeroTier.get("ascended")
],
weights=[5169, 4370, 461],
)[0]
hero = random.choice([*Hero.get_faction_heroes(*Faction.four_factions(), tier=tier)])

if hero.tier.name.casefold() == "ascended":
self.pull_counter[user_id] = 0

return random.choices(heroes)[0]
return hero

@hero.command(name="pull")
async def hero_pull(self, ctx: commands.Context, number: int = 10):
Expand Down Expand Up @@ -149,6 +183,15 @@ async def hero_pull(self, ctx: commands.Context, number: int = 10):
file = self.img_to_file(img)
await ctx.send(file=file)

@checks.is_owner()
@hero.command(name="purge")
async def hero_purge(self, ctx):
"""Purges all pre-rendered frames of heroes."""
save_dir = Path(f"images/frames/rendered/")
shutil.rmtree(save_dir)
save_dir.mkdir(exist_ok=True)
await ctx.send("All pre-rendered hero frames have been removed.")


def setup(bot):
bot.add_cog(HeroImg(bot))
Empty file.
7 changes: 3 additions & 4 deletions dreaf/game/heroes/ascensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, name: str, level_cap: int, aliases: t.List[str]):
def img_frame(self) -> Image:
img = Image.open(Path(f"images/frames/frame_{self.name.casefold().strip('+')}.png"))
if self.is_plus:
corners = Image.open(Path(f"images/frames/heroes/corners_{self.name.casefold().strip('+')}.png"))
corners = Image.open(Path(f"images/frames/corners_{self.name.casefold().strip('+')}.png"))
img = Image.alpha_composite(img, corners)
return img

Expand All @@ -35,8 +35,6 @@ def is_plus(self):

@classmethod
async def convert(cls, _ctx, arg: str):
if arg in ["none", "n", "unknown", "unk", "?"]:
return cls.none()
return cls.get(arg)

@classmethod
Expand All @@ -49,6 +47,8 @@ def get(cls, name: str):
cls.cache[asc.name.casefold()] = asc
for alias in asc.aliases:
cls.cache[alias.casefold()] = asc
for n in ["none", "n", "unknown", "unk", "?"]:
cls.cache[n] = cls.none()
return cls.cache.get(name.casefold())

@staticmethod
Expand Down Expand Up @@ -137,4 +137,3 @@ def _create_table(cls):
@classmethod
def none(cls):
return cls("none", 0, [])

37 changes: 30 additions & 7 deletions dreaf/game/heroes/factions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import csv
import logging
import sqlite3
Expand All @@ -15,36 +17,57 @@

class Faction(db.Table):
default_data = data_path / "factions.csv"
cache = dict()
factions = dict()

def __init__(self, name: str, emblem_cap: int, aliases: t.List[str]):
self.name = name
self.emblem_cap = emblem_cap
self.aliases = aliases
self.heroes = set()

def __str__(self):
return self.name.title()

def __repr__(self):
return f"<Faction '{self}'>"

def img_frame_icon(self):
return Image.open(Path(f"images/frames/faction_{self.name.casefold()}.png"))

def img_icon(self):
def img_icon(self, size: int = None):
if size:
icon = Image.open(Path(f"images/factions/{self.name.casefold()}.png"))
icon.thumbnail((size, size))
return icon
return Image.open(Path(f"images/factions/{self.name.casefold()}.png"))

@classmethod
def celepogeans(cls) -> t.Tuple[Faction, Faction]:
print(Faction.get("Hypogean"))
return Faction.get("Celestial"), Faction.get("Hypogean")

@classmethod
def four_factions(cls) -> t.Tuple[Faction, Faction, Faction, Faction]:
return Faction.get("Wilder"), Faction.get("Mauler"), Faction.get("Lightbearer"), Faction.get("Graveborn")

@classmethod
async def convert(cls, _ctx, arg: str):
if arg in ["unknown", "unk", "?", "any", "none"]:
return cls.unknown()
return cls.get(arg)

@classmethod
def get(cls, name: str):
if not cls.cache:
def get(cls, name: str) -> t.Optional[Faction]:
if not cls.factions:
print("Faction cache being built.")
for data in cls._select_all():
data = dict(data)
data['aliases'] = data['aliases'].split(',')
f = cls(**data)
cls.cache[f.name.casefold()] = f
cls.factions[f.name.casefold()] = f
for alias in f.aliases:
cls.cache[alias.casefold()] = f
return cls.cache.get(name.casefold())
cls.factions[alias.casefold()] = f
return cls.factions.get(name.casefold())

@staticmethod
def _select(name):
Expand Down
Loading

0 comments on commit b49b2c3

Please sign in to comment.