async def fleet(ctx): """Base command for fleet management, shows the current fleet.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return if (not ctx.invoked_subcommand): did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) if(len(fleet.ships) > 0): ins = fleet.get_ship_instances() fleet_lvl = sum(x.level for x in ins) // len(ins) embed = discord.Embed(title=namesub("%s's <fleet.title>") % str(ctx.author)) embed.color = 524358 flag = ins.pop(0) embed.add_field(name=namesub('<ship.title>'), value=flag.base().stype + " " + flag.base().name + " (*)\n" + "\n".join([x.base().stype + " " + x.base().name for x in ins]), inline=True) ins.insert(0, flag) embed.add_field(name="Level", value="\n".join( [str(x.level) for x in ins]), inline=True) embed.add_field(name="ID", value="\n".join( ["%04d" % (x.invid) for x in ins]), inline=True) embed.set_footer(text=namesub("<fleet.title> level %d") % fleet_lvl) await ctx.send(embed=embed) else: await ctx.send(namesub("<fleet.title> %s is empty!" % (1)))
async def f_add(ctx, shipid: int): """Add a ship to the user's fleet.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ins = ins.pop() if (shipid not in fleet.ships): if (not fleet.has_similar(ins.sid)): if (len(fleet.ships) < setting('fleets.fleet_capacity')): fleet.ships.append(shipid) fleet.update() await ctx.send(namesub("Added %s to <fleet> %s\n\n%s: *%s*") % ( ins.base().name, 1, ins.base().name, ins.base().get_quote('fleet_join'))) else: await ctx.send(namesub("<fleet.title> %s is full!" % (1))) else: await ctx.send(namesub("You already have another %s in <fleet> %s!") % (ins.base().name, 1)) else: await ctx.send(namesub("%s is already in <fleet> %s!") % (ins.base().name, 1)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def cooldowns(ctx): """Show how much time left the user has before performing actions.""" did = ctx.author.id cd_check = [] if (setting('features.drop_enabled')): cd_check.append(("Last_Drop", "Drop", DROP_COOLDOWN)) if (setting('features.training_enabled')): cd_check.append(("Last_Training", namesub("<fleet.title> Training"), TRAINING_COOLDOWN)) if (setting('features.crafting_enabled')): cd_check.append(("Last_Craft", "Crafting", CRAFTING_COOLDOWN)) if (len(cd_check) == 0): await ctx.send("That feature is not enabled.") return msg = "Current cooldowns for %s:\n" % ctx.author.display_name msg += "```\n" for cd, name, cd_s in cd_check: t = userinfo.check_cooldown(did, cd, cd_s, set_if_off=False) if (t > 0): hrs = t // 3600 min = t // 60 % 60 sec = t % 60 msg += "%s: %dh%02dm%02ds remaining\n" % (name, hrs, min, sec) else: msg += "%s: Available!\n" % (name) msg += "```" await ctx.send(msg)
async def remodel(ctx, shipid: int): """Remodel the given ship.""" if (not setting('features.levels_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ship_instance = ins.pop() base = ship_instance.base() if (base.remodels_into): if (ship_instance.is_remodel_ready()): old_name = base.name ship_instance.sid = base.remodels_into base = ship_instance.base() new_name = base.name userinfo.update_ship_sid(ship_instance) image_file = imggen.generate_ship_card(ctx.bot, ship_instance) await ctx.send(file=discord.File( io.BytesIO(image_file.getvalue()), filename="image.png"), content="%s: *%s*" % (new_name, base.get_quote('remodel') )) logging.info("[Remodel] %s (%s) remodelled %s into %s" % (str(ctx.author), did, old_name, new_name)) else: await ctx.send("%s isn't ready for a remodel just yet." % ( base.name)) else: await ctx.send("%s doesn't have another remodel." % (base.name)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def f_clear(ctx): """Clear a user's fleet.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) fleet.ships = [] fleet.update() await ctx.send(namesub("Cleared <fleet> %s!") % (1))
async def f_flag(ctx, flagship: int): """Set the flagship for the user's fleet.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == flagship] if (len(ins) > 0): ins = ins.pop() cancel = False if (len(fleet.ships) > 0): old_flag = fleet.ships.pop(0) if (not old_flag == flagship): if (flagship in fleet.ships): fleet.ships.remove(flagship) else: if (len(fleet.ships) > setting('fleets.fleet_capacity')): cancel = True await ctx.send(namesub("<fleet.title> %s is full!") % (1)) if ins.sid in map(lambda x: [y for y in inv.inventory if y.invid == x].pop().sid, fleet.ships): cancel = True await ctx.send(namesub("You already have another %s in <fleet> " "%s!") % (ins.base().name, 1)) fleet.ships.append(old_flag) else: cancel = True await ctx.send(namesub("%s is already <flagship> of <fleet> %s!") % ( ins.base().name, 1)) fleet.ships.insert(0, flagship) else: fleet.ships = [flagship, ] if (not cancel): fleet.update() await ctx.send(namesub("Set %s as the <flagship> of <fleet> %s\n\n%s: *%s*") % ( ins.base().name, 1, ins.base().name, ins.base().get_quote('fleet_join'))) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( flagship))
async def f_rem(ctx, shipid: int): """Remove a ship from a user's fleet.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ins = ins.pop() base = ins.base() if (shipid in fleet.ships): fleet.ships.remove(shipid) fleet.update() await ctx.send(namesub("Removed %s from <fleet> %s!") % (base.name, 1)) else: await ctx.send(namesub("%s isn't in <fleet> %s!") % (base.name, 1)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def f_set(ctx, *ships): """Set the user's fleet to the given ships.""" if (not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return did = ctx.author.id fleet = userinfo.UserFleet.instance(1, did) inv = userinfo.get_user_inventory(did) sids_raw = map(int, ships) sids_raw = [x for x in sids_raw if x > 0 and x in map(lambda n: n.invid, inv.inventory)] # check for no dupes while still keeping order sids = [] for x in sids_raw: if x in sids: continue sid = [y for y in inv.inventory if y.invid == x].pop().sid if sid in map(lambda y: [z for z in inv.inventory if z.invid == y] .pop().sid, sids): continue sids.append(x) if (len(sids) == 0): await ctx.send(namesub("Please include at least one valid <ship.title> ID")) elif(len(sids) > setting('fleets.fleet_capacity')): await ctx.send(namesub("Too many <ship_plural> in the <fleet>!")) else: fleet.ships = sids fleet.update() strs = fleet_strings(inv, fleet) flag = strs.pop(0) line_base = [x for x in inv.inventory if x.invid == sids[0]].pop().base() if (len(strs) > 0): await ctx.send(namesub("Set <fleet> %s to: <flagship.title> %s, <ship_plural> %s\n\n%s: *%s*") % (1, flag, ", ".join(strs), line_base.name, line_base.get_quote('fleet_join'))) else: await ctx.send(namesub("Set <fleet> %s to: <flagship.title> %s\n\n%s: *%s*") % (1, flag, line_base.name, line_base.get_quote('fleet_join')))
async def craft(ctx, fuel: int, ammo: int, steel: int, bauxite: int): """Craft a random ship based on the user's inputted resources.""" did = ctx.author.id user = userinfo.get_user(did) if (not setting('features.crafting_enabled') or not setting('features.resources_enabled')): await ctx.send("That feature is not enabled.") return if (userinfo.has_space_in_inventory(did)): cd = userinfo.check_cooldown( did, 'Last_Craft', CRAFTING_COOLDOWN, set_if_off=False) if (cd == 0): min_craft = setting('resources.min_crafting') if (fuel >= min_craft[0] and ammo >= min_craft[1] and steel >= min_craft[2] and bauxite >= min_craft[3]): if (user.has_enough(fuel, ammo, steel, bauxite)): craft = craftinghandler.get_craft_from_resources( did, fuel, ammo, steel, bauxite) user.mod_fuel(-fuel) user.mod_ammo(-ammo) user.mod_steel(-steel) user.mod_bauxite(-bauxite) inv = userinfo.get_user_inventory(did) inv.add_to_inventory(craft) # set cooldown userinfo.check_cooldown( did, 'Last_Craft', CRAFTING_COOLDOWN, set_if_off=True) image_file = imggen.generate_ship_card(ctx.bot, craft) ship_base = craft.base() await ctx.send( file=discord.File(io.BytesIO(image_file.getvalue()), filename="image.png"), content="%s just crafted %s!\n\n%s: *%s*" % ( ctx.author.display_name, ship_base.name, ship_base.name, ship_base.get_quote('intro'))) logging.info("[Craft] %s (%s) crafted %s using recipe " "%s/%s/%s/%s" % (str(ctx.author), did, ship_base.name, fuel, ammo, steel, bauxite)) else: await ctx.send("Not enough resources!") else: await ctx.send("Use at least 30 of each resource") else: min = cd // 60 sec = cd % 60 await ctx.send("You have %dm%02ds remaining until you can craft " "another ship" % (min, sec)) else: await ctx.send(namesub("Your inventory is full! You can scrap a <ship.title> with " "`%sscrap [<ship.title> ID]`") % COMMAND_PREFIX)
async def add_ship(ctx, user: discord.Member, ship_name): """Admin command to add a ship to a user's inventory.""" inv = userinfo.get_user_inventory(user.id) targ = None for ship in ship_stats.get_all_ships(): if (ship.name.lower() == ship_name.lower() or ship.name.lower() .replace(' ', '_') == ship_name.lower()): targ = ship break if (targ): ins = ship_stats.ShipInstance.new(targ.sid, user.id) inv.add_to_inventory(ins) await ctx.send("Added %s to %s's inventory" % (targ.name, str(user))) logging.info("[ADMIN_ADD] Added %s to %s's (%s) inventory" % (targ.name, str(user), user.id)) else: await ctx.send(namesub("Cannot find <ship.title> '%s'") % ship_name)
async def show(ctx, shipid: int): """Show the specified ship from the user's inventory.""" did = ctx.author.id inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ship_instance = ins.pop() base = ship_instance.base() image_file = imggen.generate_ship_card(ctx.bot, ship_instance) if (ship_instance.level > setting('levels.level_cap')): quote = base.get_quote('married') else: quote = base.get_quote('idle') await ctx.send(file=discord.File(io.BytesIO(image_file.getvalue()), filename="image.png"), content="%s: *%s*" % (base.name, quote)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def scrap(ctx, shipid: int): """Scrap the given ship from the user's inventory.""" did = ctx.author.id user = userinfo.get_user(did) inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ship_instance = ins.pop() base = ship_instance.base() user.mod_fuel(setting_random('resources.scrap_gain.fuel')) user.mod_ammo(setting_random('resources.scrap_gain.ammo')) user.mod_steel(setting_random('resources.scrap_gain.steel')) user.mod_bauxite(setting_random('resources.scrap_gain.bauxite')) inv.remove_from_inventory(shipid) await ctx.send("Scrapped %s... <:roosad:434916104268152853>" % ( base.name)) logging.info("[Scrap] %s (%s) scrapped ship %s with inv id %s" % (str(ctx.author), did, base.name, shipid)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def drop(ctx): """Drop a random ship for the user.""" did = ctx.author.id if (not setting('features.drop_enabled')): await ctx.send("That feature is not enabled.") return if (userinfo.has_space_in_inventory(did)): cd = userinfo.check_cooldown(did, 'Last_Drop', DROP_COOLDOWN) if (cd == 0): drop = drophandler.get_random_drop(did, only_droppable=True) ship_base = drop.base() ship_name = ship_base.name ship_rarity = ship_base.rarity rarity = setting('rarities') inv = userinfo.get_user_inventory(did) inv.add_to_inventory(drop) image_file = imggen.generate_ship_card(ctx.bot, drop) await ctx.send( file=discord.File( io.BytesIO(image_file.getvalue()), filename="image.png"), content="%s got %s! (%s)\n\n%s: *%s*" % ( ctx.author.display_name, ship_name, rarity[ship_rarity - 1], ship_name, ship_base.get_quote('intro'))) logging.info("[Drop] %s (%s) received %s from a drop" % (str(ctx.author), did, ship_name)) else: hrs = cd // 3600 min = cd // 60 % 60 sec = cd % 60 await ctx.send("You have %dh%02dm%02ds remaining until you can" " get your next drop" % (hrs, min, sec)) else: await ctx.send(namesub("Your inventory is full! You can scrap a <ship.title> with" " `%sscrap [<ship.title> ID]`") % COMMAND_PREFIX)
async def marry(ctx, shipid: int): """Allow the user to marry a level 99 ship, increasing its level cap.""" if (not setting('features.marriage_enabled') or not setting('features.levels_enabled')): await ctx.send("This feature is not enabled.") did = ctx.author.id user = userinfo.get_user(did) inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ship_instance = ins.pop() base = ship_instance.base() if (ship_instance.level == setting('levels.level_cap')): ring_req = setting('levels.marriage_ring_required') rings = user.rings if (rings > 0 or not ring_req): ship_instance.level = setting('levels.level_cap') + 1 ship_instance.exp = 0 ship_instance.add_exp(0) if (ring_req): user.use_ring() ship_name = base.name image_file = imggen.generate_ship_card(ctx.bot, ship_instance) await ctx.send(file=discord.File( io.BytesIO(image_file.getvalue()), filename="image.png"), content="%s: *%s*" % (ship_name, base.get_quote('married') )) logging.info("[Marriage] %s (%s) married their %s" % (str(ctx.author), did, ship_name)) else: await ctx.send("You don't have any more rings.") else: await ctx.send("%s isn't ready for marriage yet." % (base.name)) else: await ctx.send(namesub("<ship.title> with ID %s not found in your inventory") % ( shipid))
async def train(ctx, dif: int=-1): """Train a user's fleet given the difficulty, or show training options.""" did = ctx.author.id difs = fleet_training.ALL_DIFFICULTIES if (not setting('features.training_enabled') or not setting('features.levels_enabled') or not setting('features.fleets_enabled')): await ctx.send("That feature is not enabled.") return if (dif == -1): description = "Difficulties:\n" description += "\n".join([namesub("#%s. %s: Min <flagship> level %s, Recommended" " <fleet> level %s.") % (x + 1, difs[x].name, difs[x].min_flag, difs[x].avg_lvl) for x in range(len(difs))]) footer = "Type %strain (#) to train a fleet with a difficulty" % ( COMMAND_PREFIX) embed = discord.Embed(title=namesub("<fleet.title> Training"), description=description) embed.set_footer(text=footer) await ctx.send(embed=embed) else: if (dif > 0 and dif <= len(difs)): dif_targ = difs[dif - 1] fleet = userinfo.UserFleet.instance(1, did) if (len(fleet.ships) > 0): ins = fleet.get_ship_instances() flag = ins[0] if (flag.level >= dif_targ.min_flag): rsc = dif_targ.resource_costs(fleet) rsc = tuple(map(int, rsc)) user = userinfo.get_user(did) if (user.has_enough(*rsc)): cd = userinfo.check_cooldown( did, "Last_Training", TRAINING_COOLDOWN) if (cd == 0): # conditions passed rank = dif_targ.rank_training(fleet) exp_rew_base = rank.exp_mult \ * dif_targ.exp_reward_base exp_rew_split = rank.exp_mult \ * dif_targ.exp_reward_split exp = [exp_rew_base] * len(ins) exp_per = exp_rew_split // len(ins) + 1 exp[0] += exp_per exp = list(map(lambda x: x + exp_per, exp)) lvl_dif = [x.level for x in ins] for i in range(len(ins)): ins[i].add_exp(exp[i]) lvl_dif[i] = ins[i].level - lvl_dif[i] user.mod_fuel(-rsc[0]) user.mod_ammo(-rsc[1]) user.mod_steel(-rsc[2]) user.mod_bauxite(-rsc[3]) embed = discord.Embed(title="Training %s" % ( "Success" if rank.is_success else "Failed")) embed.color = 65280 if rank.is_success \ else 16711680 embed.description = "Rank %s | %s Difficulty" % ( rank.symbol, dif_targ.name) flag = ins.pop(0) embed.add_field(name="EXP Gain", value=flag.base( ).name + " (*)\n" + "\n".join([x.base().name for x in ins]), inline=True) embed.add_field( name="--------", value="\n".join(["+%g EXP" % x for x in exp] )) ins.insert(0, flag) embed.add_field(name="--------", value="\n".join( ["Level %s (+%s)" % (ins[i].level, lvl_dif[i]) for i in range(len(ins))])) if (setting('features.resources_enabled')): embed.set_footer( text=namesub("Used %g <fuel>, %g <ammo>, %g <steel>, %g " "<bauxite>") % rsc) await ctx.send(embed=embed) logging.info("[Training] %s (%s) completed " "training level %s with rank %s" % ( str(ctx.author), did, dif_targ.name, rank.symbol)) else: hrs = cd // 3600 min = cd // 60 % 60 sec = cd % 60 await ctx.send(namesub("You have %dh%02dm%02ds remaining " "until you can train your <fleet> " "again") % (hrs, min, sec)) else: await ctx.send(namesub("Not enough resources! (Required: %g " "<fuel>, %g <ammo>, %g <steel>, %g <bauxite>)") % rsc) else: await ctx.send(namesub("<flagship.title> isn't a high enough level! " "(Needs to be at least %s)") % ( dif_targ.min_flag)) else: await ctx.send(namesub("<fleet.title> %s is empty!") % (1)) else: await ctx.send("No such difficulty #%s" % dif)
def generate_ship_card(bot, ship_instance): """Return a BytesIO object of a card image of the given ship. Parameters ---------- bot : discord.ext.commands.Bot The bot being run. ship_instance : ShipInstance The ship to display. """ base = ship_instance.base() img = ship_stats.get_rarity_backdrop(base.rarity) layout = CONFIG_DATA['ship_card'] obj_small_identifier = layout['small_identifier'] obj_name = layout['name'] obj_class_name = layout['class_name'] obj_level_indicator = layout['level_indicator'] obj_level_progress = layout['level_progress'] obj_next_remodel = layout['next_remodel'] obj_owned_by = layout['owned_by'] obj_main_image = layout['main_image'] use_damaged = False # TODO make this check if ship is damaged img_full = base.get_cg(dmg=use_damaged) if (obj_main_image['enabled']): img_w, img_h = img_full.size targ_width = int(obj_main_image['targ_height'] * (img_w / img_h)) x_offset = int(obj_main_image['x_offset'] - (targ_width / 2)) img_full = img_full.resize((targ_width, obj_main_image['targ_height']), Image.BICUBIC) img.paste( img_full, (x_offset, obj_main_image['y_offset']), mask=img_full) if (ship_instance.level > setting('levels.level_cap')): ring = Image.open(small_ico_ring_img) ring = ring.resize((60, 60)) img.paste(ring, (20, 20), mask=ring) if (obj_name['enabled']): draw_object(img, obj_name, base.name) if (obj_class_name['enabled']): draw_object(img, obj_class_name, "%s %s" % (base.class_name, ship_stats.get_ship_type(base.stype).full_name)) if (setting('features.levels_enabled')): if (obj_level_indicator['enabled']): draw_object(img, obj_level_indicator, "Level %s" % (ship_instance.level)) if (obj_level_progress['enabled'] and (ship_instance.level > 1 or ship_instance.exp > 0) and ship_instance.level != setting('levels.level_cap') and ship_instance.level < setting('levels.level_cap_married')): exp = ship_instance.exp req = ship_instance.exp_req() draw_object(img, obj_level_progress, "%s / %s EXP (%.02f%%)" % (exp, req, 100.0 * exp / req)) if (base.remodels_into and obj_next_remodel['enabled']): r_base = ship_stats.ShipBase.instance(base.remodels_into) draw_object(img, obj_next_remodel, "Next Remodel: %s (Level %s)" % ( r_base.name, base.remodel_level)) if (obj_small_identifier['enabled']): draw_object(img, obj_small_identifier, "%s-%04d" % (base.stype, ship_instance.invid)) if (obj_owned_by['enabled']): display_name = "Unknown User" for g in bot.guilds: owner = g.get_member(ship_instance.owner) if (owner): display_name = "%s#%s" % (owner.name, owner.discriminator) break draw_object(img, obj_owned_by, namesub("Part of %s's <fleet.title>" % (display_name))) r = io.BytesIO(b'') img.save(r, format="PNG") return r
def generate_inventory_screen(member, page, only_dupes=False): """Return a BytesIO object of the user's inventory image. Parameters ---------- member : discord.Member The user to generate the inventory of. page : int The page to show. only_dupes : bool If True, only display ships which the user has two or more of. """ discord_id = member.id user = userinfo.get_user(discord_id) inv = userinfo.get_user_inventory(discord_id) layout = CONFIG_DATA['inventory'] w, h = layout['image_size'] antialias_value = 2 w *= antialias_value h *= antialias_value sx, sy = layout['per_row'], layout['per_column'] cw = int(w / sx) ch = int(h / sy) h += layout['lower_padding'] * antialias_value ship_pool = inv.inventory if (only_dupes): new_pool = [] first_bases = {} for s in ship_pool: first_bases[s.sid] = s.base().get_first_base() for i in range(len(ship_pool)): s = ship_pool.pop(0) if (first_bases[s.sid].sid in map(lambda x: first_bases[x.sid].sid, new_pool) or first_bases[s.sid].sid in map(lambda x: first_bases[x.sid].sid, ship_pool)): new_pool.append(s) ship_pool = new_pool ships_per_page = sx * sy pages_needed = (len(ship_pool) // ships_per_page) + \ (0 if len(ship_pool) % ships_per_page == 0 and len(ship_pool) > 0 else 1) if (page < 1): page = 1 elif (page > pages_needed): page = pages_needed img = Image.new(size=(w, h), mode="RGB", color=(255, 255, 255)) draw = ImageDraw.Draw(img) shade = False indx = 0 indx += (ships_per_page * (page - 1)) for xi in range(sx): for yi in range(sy): ship = ship_pool[indx] if indx < len(ship_pool) else None shade_color = (("filled_color1" if shade else "filled_color2") if ship else ("empty_color1" if shade else "empty_color2")) rbg = None if (ship): rbg = ship_stats.get_rarity_backdrop(ship.base().rarity) rbg = rbg.resize((cw, ch)) fleet = userinfo.UserFleet.instance(1, discord_id) if (ship.invid in fleet.ships): flag = fleet.ships.index(ship.invid) == 0 if flag: shade_color = 'flag_border_color' else: shade_color = "fleet_color1" if shade else "fleet_color2" elif (ship.base().has_seasonal_cg()): shade_color = "seasonal_color1" if shade else "seasonal_color2" shade_color = tuple(layout[shade_color]) x, y = (xi * cw, yi * ch) draw.rectangle((x, y, x + cw, y + ch), fill=shade_color) if (rbg): img.paste(rbg, (x, y)) if (ship): base = ship.base() font = ImageFont.truetype("fonts/trebucbd.ttf", ch * 1 // 2) num_str = "%s-%04d" % (base.stype, ship.invid) draw_squish_text(img, (x + cw * 3 // 4, y + ch * 1 // 4), num_str, font, cw * 7 // 16 - 2, color=(0, 0, 0)) if (setting('features.levels_enabled')): if (setting('features.marriage_enabled') and ship.level > setting('levels.level_cap')): ring = Image.open(small_ico_ring_img) ring = ring.resize((ch // 3 - 4, ch // 3 - 4)) ring_loc = (x + cw * 8 // 9 - 2, y + ch * 5 // 8 + 2) draw.ellipse( (ring_loc, tuple(map(sum, zip(ring_loc, ring.size)))), fill=(0, 0, 0)) img.paste(ring, ring_loc, mask=ring) font = ImageFont.truetype( "fonts/trebucbd.ttf", ch * 3 // 8) lvl_str = "Lv. %02d" % (ship.level) draw_squish_text(img, (x + 2 + cw * 11 // 16, y + ch * 3 // 4 - 2), lvl_str, font, cw // 3 - 4, color=(0, 0, 0)) if (ship.is_remodel_ready()): draw.rectangle((x + cw // 2 + 2, y + ch * 9 // 16, x + cw * 31 // 32, y + ch * 15 // 16), outline=(50, 0, 250), width=2) cir_start_x = x + 3 cir_start_y = y + 3 use_damaged = False # TODO check if use damaged image ico = base.get_cg(ico=True, dmg=use_damaged) ico = ico.resize((int(ch * 1.5) - 6, ch - 6), Image.BILINEAR) pxls = ico.load() grad_start = int(ico.size[0] * 0.75) grad_end = ico.size[0] for ix in range(grad_start, grad_end): for iy in range(ico.size[1]): fade_amt = (ix - grad_start) / (grad_end - grad_start) fade_amt *= fade_amt new_alpha = int(pxls[ix, iy][3] * (1 - fade_amt)) pxls[ix, iy] = pxls[ix, iy][:3] + (new_alpha,) img.paste(ico, (cir_start_x, cir_start_y), ico) draw.rectangle((x, y, x + cw - 1, y + ch - 1), outline=shade_color, width=3) shade = not shade indx += 1 if(sy % 2 == 0): shade = not shade draw = ImageDraw.Draw(img) # start position of footer x, y = (0, layout['image_size'][1] * antialias_value) fw, fh = (w, layout['lower_padding'] * antialias_value) # size of footer display_name = "%s#%s" % (member.name, member.discriminator) font = ImageFont.truetype("fonts/framd.ttf", fh * 3 // 4) o_txt = namesub("<ship_plural.title>") if not only_dupes else "Dupes" draw.text((x + 10, y + fh // 8), "%s's %s" % (display_name, o_txt), font=font, fill=(0, 0, 0)) font = ImageFont.truetype("fonts/framdit.ttf", fh // 2) pg_txt = "Page %s of %s" % (page, pages_needed) pgw, pgh = draw.textsize(pg_txt, font=font) pgx, pgy = (fw - pgw - 2, y + fh - pgh - 2) draw.text((pgx, pgy), pg_txt, font=font, fill=(50, 50, 50)) font = ImageFont.truetype("fonts/trebucbd.ttf", fh * 3 // 8) rsc_x, rsc_y = (fw * 21 // 32, y + 1) txt_fuel = "%05d" % (user.fuel) txt_ammo = "%05d" % (user.ammo) txt_steel = "%05d" % (user.steel) txt_bauxite = "%05d" % (user.bauxite) txt_ships = "%03d / %03d" % (len(ship_pool), user.shipslots) txt_rings = "%01d" % (user.rings) txt_w, txt_h = draw.textsize(txt_fuel, font) ico_size = (fh * 3 // 8 + 2, fh * 3 // 8 + 2) if (setting('features.resources_enabled')): ico_fuel = Image.open(DIR_PATH + '/icons/fuel.png').resize(ico_size, Image.LINEAR) ico_ammo = Image.open(DIR_PATH + '/icons/ammo.png').resize(ico_size, Image.LINEAR) ico_steel = Image.open(DIR_PATH + '/icons/steel.png').resize(ico_size, Image.LINEAR) ico_bauxite = Image.open(DIR_PATH + '/icons/bauxite.png') \ .resize(ico_size, Image.LINEAR) ico_ships = Image.open(DIR_PATH + '/icons/ship.png').resize(ico_size, Image.LINEAR) if (setting('features.marriage_enabled') and setting('levels.marriage_ring_required')): ico_rings = Image.open(DIR_PATH + '/icons/marriagepapers.png') \ .resize(ico_size, Image.LINEAR) x_off = ico_size[0] + txt_w + 6 y_off = ico_size[1] + 2 toff_x, toff_y = (ico_size[0] + 2, (ico_size[1] - txt_h) // 2) if (setting('features.resources_enabled')): draw.text((rsc_x + toff_x, rsc_y + toff_y), txt_fuel, font=font, fill=(0, 0, 0)) draw.text((rsc_x + toff_x, rsc_y + toff_y + y_off), txt_ammo, font=font, fill=(0, 0, 0)) draw.text((rsc_x + toff_x + x_off, rsc_y + toff_y), txt_steel, font=font, fill=(0, 0, 0)) draw.text((rsc_x + toff_x + x_off, rsc_y + toff_y + y_off), txt_bauxite, font=font, fill=(0, 0, 0)) draw.text((rsc_x + toff_x + x_off * 2, rsc_y + toff_y), txt_ships, font=font, fill=(0, 0, 0)) if (setting('features.marriage_enabled') and setting('levels.marriage_ring_required')): draw.text((rsc_x + toff_x + int(x_off * 3.5), rsc_y + toff_y), txt_rings, font=font, fill=(0, 0, 0)) if (setting('features.resources_enabled')): img.paste(ico_fuel, (rsc_x, rsc_y), mask=ico_fuel) img.paste(ico_ammo, (rsc_x, rsc_y + y_off), mask=ico_fuel) img.paste(ico_steel, (rsc_x + x_off, rsc_y), mask=ico_fuel) img.paste(ico_bauxite, (rsc_x + x_off, rsc_y + y_off), mask=ico_fuel) img.paste(ico_ships, (rsc_x + x_off * 2, rsc_y), mask=ico_ships) if (setting('features.marriage_enabled') and setting('levels.marriage_ring_required')): img.paste(ico_rings, (rsc_x + int(x_off * 3.5), rsc_y), mask=ico_rings) img = img.resize((w // antialias_value, h // antialias_value), Image.ANTIALIAS) r = io.BytesIO() img.save(r, format="PNG") return r
import datetime import subprocess import logging from settings import setting, namesub, setting_random COMMAND_PREFIX = setting('command_prefix') bot = commands.Bot(command_prefix=COMMAND_PREFIX, case_insensitive=True, activity=discord.Game(type=0, name=setting('bot_playing'))) DROP_COOLDOWN = setting('cooldowns.drop') CRAFTING_COOLDOWN = setting('cooldowns.craft') TRAINING_COOLDOWN = setting('cooldowns.train') @bot.command(help=namesub("Show a <ship.title> from your inventory"), usage="[Ship ID]") async def show(ctx, shipid: int): """Show the specified ship from the user's inventory.""" did = ctx.author.id inv = userinfo.get_user_inventory(did) ins = [x for x in inv.inventory if x.invid == shipid] if (len(ins) > 0): ship_instance = ins.pop() base = ship_instance.base() image_file = imggen.generate_ship_card(ctx.bot, ship_instance) if (ship_instance.level > setting('levels.level_cap')): quote = base.get_quote('married') else: quote = base.get_quote('idle') await ctx.send(file=discord.File(io.BytesIO(image_file.getvalue()), filename="image.png"),