import copy import json import os from pathlib import Path import datetime import numpy import random from PIL import Image, PngImagePlugin, ImageDraw, ImageFont from .gacha_info import init_user_info, user_info, save_user_info from ..utils.util import pil2b64 RES_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'res', 'gacha_res') font_path = os.path.join(RES_PATH, 'zh-cn.ttf') count_font = ImageFont.truetype(font_path, 35) time_font = ImageFont.truetype(font_path, 20) with open(os.path.join(RES_PATH, 'type.json'), 'r', encoding="utf-8") as fp: type_json = json.load(fp) cache_img = {} cache_item = {} def random_int(): return numpy.random.randint(low=0, high=10000, size=None, dtype='l') # 抽卡概率来自https://www.bilibili.com/read/cv10468091 # 角色抽卡概率 def character_probability(rank, count): ret = 0 count += 1 if rank == 5 and count <= 73: ret = 60 elif rank == 5 and count >= 74: ret = 60 + 600 * (count - 73) elif rank == 4 and count <= 8: ret = 510 elif rank == 4 and count >= 9: ret = 510 + 5100 * (count - 8) return ret # 武器抽卡概率 def weapon_probability(rank, count): ret = 0 count += 1 if rank == 5 and count <= 62: ret = 70 elif rank == 5 and count <= 73: ret = 70 + 700 * (count - 62) elif rank == 5 and count >= 74: ret = 7770 + 350 * (count - 73) elif rank == 4 and count <= 7: ret = 600 elif rank == 4 and count == 8: ret = 6600 elif rank == 4 and count >= 9: ret = 6600 + 3000 * (count - 8) return ret def get_pool_type(gacha_type): if gacha_type == 301 or gacha_type == 400: return 'role' if gacha_type == 200: return 'permanent' return 'weapon' def get_rank(uid, pool_str): value = random_int() if pool_str == 'weapon': index_5 = weapon_probability(5, user_info[uid]["gacha_list"][("gacha_5_%s" % pool_str)]) index_4 = weapon_probability(4, user_info[uid]["gacha_list"][("gacha_4_%s" % pool_str)]) + index_5 else: index_5 = character_probability(5, user_info[uid]["gacha_list"][("gacha_5_%s" % pool_str)]) index_4 = character_probability(4, user_info[uid]["gacha_list"][("gacha_4_%s" % pool_str)]) + index_5 if value <= index_5: return 5 elif value <= index_4: return 4 else: return 3 def is_Up(uid, rank, pool_str): if pool_str == 'permanent': return False elif pool_str == 'weapon': return random_int() <= 7500 or user_info[uid]["gacha_list"]["is_up_%s_weapon" % rank] else: return random_int() <= 5000 or user_info[uid]["gacha_list"]["is_up_%s_role" % rank] def once(uid, gacha_data): role = {} init_user_info(uid) pool_str = get_pool_type(gacha_data['gacha_type']) # 判定星级 rank = get_rank(uid, pool_str) # 是否为up if rank != 3: is_up = is_Up(uid, rank, pool_str) user_info[uid]["gacha_list"]["wish_total"] += 1 if rank == 3: role = random.choice(gacha_data['r3_prob_list']) user_info[uid]["gacha_list"][("gacha_4_%s" % pool_str)] += 1 user_info[uid]["gacha_list"][("gacha_5_%s" % pool_str)] += 1 role['count'] = 1 else: if rank == 5 and pool_str == 'weapon' and user_info[uid]["gacha_list"]["dg_time"] == 2 and "pool_type" not in gacha_data: role['item_name'] = user_info[uid]["gacha_list"]["dg_name"] role['item_type'] = '武器' role['rank'] = rank elif is_up: role = random.choice(gacha_data['r%s_up_items' % rank]) user_info[uid]["gacha_list"]["wish_%s_up" % rank] += 1 role['rank'] = rank else: role = random.choice(gacha_data['r%s_prob_list' % rank]) while True: role = random.choice(gacha_data['r%s_prob_list' % rank]) if role['is_up'] == 0: break if rank == 4: user_info[uid]["gacha_list"][("gacha_5_%s" % pool_str)] += 1 elif rank == 5: user_info[uid]["gacha_list"][("gacha_4_%s" % pool_str)] += 1 if pool_str == 'weapon' and "pool_type" not in gacha_data: if user_info[uid]["gacha_list"]["dg_name"] == '': role['dg_time'] = -1 elif role['item_name'] != user_info[uid]["gacha_list"]["dg_name"]: user_info[uid]["gacha_list"]["dg_time"] += 1 role['dg_time'] = user_info[uid]["gacha_list"]["dg_time"] else: user_info[uid]["gacha_list"]["dg_name"] = '' user_info[uid]["gacha_list"]["dg_time"] = 0 role['dg_time'] = 3 user_info[uid]["gacha_list"]["wish_%s" % rank] += 1 if gacha_data['gacha_type'] != 200: user_info[uid]["gacha_list"][("is_up_%s_%s" % (rank, pool_str))] = not is_up if role['item_type'] == '角色': itemname = 'role' else: itemname = 'weapon' if role['item_name'] not in user_info[uid]["role_list"]: user_info[uid]["%s_list" % itemname][role['item_name']] = {} user_info[uid]["%s_list" % itemname][role['item_name']]['数量'] = 1 user_info[uid]["%s_list" % itemname][role['item_name']]['出货'] = [] if rank == 5: user_info[uid]["%s_list" % itemname][role['item_name']]['星级'] = '★★★★★' user_info[uid]["%s_list" % itemname][role['item_name']]['出货'].append( (user_info[uid]['gacha_list']['gacha_%s_%s' % (rank, pool_str)] + 1)) else: user_info[uid]["%s_list" % itemname][role['item_name']]['星级'] = '★★★★' else: user_info[uid]["%s_list" % itemname][role['item_name']]['数量'] += 1 if rank == 5: user_info[uid]["%s_list" % itemname][role['item_name']]['出货'].append( (user_info[uid]['gacha_list']['gacha_%s_%s' % (rank, pool_str)] + 1)) role['count'] = user_info[uid]["gacha_list"]["gacha_%s_%s" % (rank, pool_str)] + 1 user_info[uid]["gacha_list"]["gacha_%s_%s" % (rank, pool_str)] = 0 save_user_info() return role async def create_item(rank, item_type, name, element, count, dg_time): bg = Image.open(os.path.join(RES_PATH, f'{rank}_background.png')).resize((143, 845)) item_img = Image.open(os.path.join(RES_PATH, item_type, f'{name}.png')) rank_img = Image.open(os.path.join(RES_PATH, f'{rank}_star.png')).resize((119, 30)) if item_type == '角色': item_img = item_img.resize((item_img.size[0] + 12, item_img.size[1] + 45)) item_img.alpha_composite(rank_img, (4, 510)) item_type_icon = Image.open(os.path.join(RES_PATH, '元素', f'{element}.png')).resize((80, 80)) item_img.alpha_composite(item_type_icon, (25, 420)) bg.alpha_composite(item_img, (3, 125)) else: bg.alpha_composite(item_img, (3, 240)) bg.alpha_composite(rank_img, (9, 635)) item_type_icon = type_json.get(name) if item_type_icon: item_type_icon = Image.open(os.path.join(RES_PATH, '类型', f'{item_type_icon}.png')).resize((100, 100)) bg.alpha_composite(item_type_icon, (18, 530)) if rank == 5 and count != -1: draw = ImageDraw.Draw(bg) if len(str(count)) == 2: draw.text((19, 750), ('[' + str(count) + '抽]'), font=count_font, fill='white') else: draw.text((26, 750), ('[' + str(count) + '抽]'), font=count_font, fill='white') if dg_time != -1: if dg_time == 3: draw.text((3, 785), ('定轨结束'), font=count_font, fill='white') else: draw.text((7, 785), ('定轨' + str(dg_time) + '/2'), font=count_font, fill='white') return bg async def ten(uid, gacha_data, sd) -> PngImagePlugin.PngImageFile: gacha_list = [] for i in range(0, 10): if gacha_data['gacha_type'] == 'all_star': role = random.choice(gacha_data['list']) role['count'] = -1 role['rank'] = 5 else: role = once(uid, gacha_data).copy() gacha_list.append(role) gacha_list.sort(key=lambda x: x["rank"], reverse=True) img: PngImagePlugin.PngImageFile img = Image.open(os.path.join(RES_PATH, 'background.png')) i = 0 for wish in gacha_list: i += 1 rank = wish['rank'] item_type = wish['item_type'] name = wish['item_name'] element = wish.get('item_attr') or type_json[name] count = wish['count'] try: dg_time = wish['dg_time'] except: dg_time = -1 i_img = await create_item(rank, item_type, name, element, count, dg_time) img.alpha_composite(i_img, (105 + (i_img.size[0] * i), 123)) img.thumbnail((1024, 768)) img2 = Image.new("RGB", img.size, (255, 255, 255)) img2.paste(img, mask=img.split()[3]) return img2 async def more_ten(uid, gacha_data, num, sd): time_str = datetime.datetime.strftime(datetime.datetime.now(), '%m-%d %H:%M') if num == 1: img = await ten(uid, gacha_data, sd) else: img = Image.new("RGB", (1024, 575 * num), (255, 255, 255)) for i in range(0, num): item_img = await ten(uid, gacha_data, sd) img.paste(item_img, (0, 575 * i)) draw = ImageDraw.Draw(img) draw.text((27, 575 * num - 30), ('@%s %s Created By 惜月の小派蒙' % (str(sd.nickname), time_str)), font=time_font, fill="#8E8E8E") return pil2b64(img, 75)