import { Application, BackendSession } from "pinus"; import { resResult, getRandomWithWeight, getRandEelm, shouldRefresh } from "../../../pubUtils/util"; import { STATUS, GACHA_ID, HERO_QUALITY_TYPE, TASK_TYPE, REFRESH_HOUR } from "../../../consts"; import { gameData } from "../../../pubUtils/data"; import { GachaListReturn, GachaResult, GachaData } from "../../../domain/activityField/gachaField"; import { UserGachaModel } from "../../../db/UserGacha"; import { refreshGacha, getFloorResult, getResultFromContentId } from "../../../services/gachaService"; import { RoleModel } from "../../../db/Role"; import { HeroModel, HeroUpdate } from "../../../db/Hero"; import { RewardInter } from "../../../pubUtils/interface"; import { handleCost, createHeroes, addItems } from "../../../services/rewardService"; import { getAfterDateByDay, getTodayZeroDate, getZeroDate } from "../../../pubUtils/timeUtil"; import { UserGachaRecModel } from "../../../db/UserGachaRec"; import { ActivityModel } from "../../../db/Activity"; import { checkTask } from "../../../services/taskService"; import { RECRUIT } from "../../../pubUtils/dicParam"; import { getAllHeroByQuality } from "../../../services/gachaService"; import { transPiece } from "../../../pubUtils/itemUtils"; import { CreateHeroParam } from "../../../domain/roleField/hero"; import roleHandler from "../../role/handler/roleHandler"; export default function (app: Application) { return new GachaHandler(app); } export class GachaHandler { constructor(private app: Application) { } /** * @description 获取抽卡列表 元宝招募、友情点招募、求贤若渴 * @param {{}} msg * @param {BackendSession} session * @memberof GachaHandler */ async getGachaList(msg: {}, session: BackendSession) { const { } = msg; const roleId: string = session.get('roleId'); let userGachaList = await UserGachaModel.findAllByRole(roleId); let list: GachaListReturn[] = []; for(let [id, dicGacha] of gameData.gacha) { if(id == GACHA_ID.TIMELIMIT) continue; // 不包括限时 let userGacha = userGachaList.find(cur => cur.gachaId == id); if(userGacha) userGacha = await refreshGacha(dicGacha, userGacha); let param = new GachaListReturn(dicGacha, userGacha); list.push(param); } return resResult(STATUS.SUCCESS, { list }); } /** * @description 抽卡,所有抽卡类型都 * @param {{ gachaId: number, activityId: number, count: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async pull(msg: { gachaId: number, activityId: number, count: number }, session: BackendSession) { const { gachaId, activityId, count } = msg; if(gachaId == undefined|| activityId == undefined || count == undefined) return resResult(STATUS.WRONG_PARMS); const roleId: string = session.get('roleId'); const roleName: string = session.get('roleName'); const sid: string = session.get('sid'); const serverId: number = session.get('serverId'); const funcs: number[] = session.get('funcs'); let { lv } = await RoleModel.findByRoleId(roleId); let dicGacha = gameData.gacha.get(gachaId); if(!dicGacha) return resResult(STATUS.DIC_DATA_NOT_FOUND); if(!dicGacha.count.includes(count)) return resResult(STATUS.WRONG_PARMS); let userGacha = await UserGachaModel.findByRole(roleId, gachaId, activityId); let { floor, freeCount, hope, point, pickHero, refFreeTime } = await refreshGacha(dicGacha, userGacha); if((gachaId == GACHA_ID.ASSIGN|| gachaId == GACHA_ID.TIMELIMIT) && pickHero) return resResult(STATUS.GACHA_NOT_ASSIGN); let userHeroes = await HeroModel.findByRole(roleId); let items: RewardInter[] = [], heroInfo: CreateHeroParam[] = [], resultList: GachaResult[] = []; for(let i = 0; i < count; i++) { // 按照一般概率抽出 let { dic: { id: base } } = getRandomWithWeight(dicGacha.percent); let contentId = getFloorResult(gachaId, base, floor); if(contentId == false) return resResult(STATUS.DIC_DATA_NOT_FOUND); let result = getResultFromContentId(contentId, lv, hope); if(result.hid > 0) { result.setSetPickHero(pickHero); let hasHero = userHeroes.find(cur => cur.hid == result.hid); if(hasHero) { // 已有转换为碎片 let { pieceId, count } = transPiece(result.hid); result.transferToPiece(pieceId, count); items.push({ id: pieceId, count }); } else { heroInfo.push({ hid: result.hid }) } } else { items.push({ id: result.id, count }); } resultList.push(result); } let costNum = count; if(dicGacha.free.count > 0) { if(count > dicGacha.free.count - freeCount) { costNum = count - dicGacha.free.count + freeCount; freeCount = dicGacha.free.count; } else { costNum = 0; freeCount += count; } } // 消耗东西 if(costNum > 0) { let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * costNum }}); let costResult = await handleCost(roleId, sid, cost); if(!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); } // 给东西 let { heroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); await addItems(roleId, roleName, sid, items); // 更新数据 point = Math.floor(count/RECRUIT.RECRUIT_BONUS); userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { freeCount, hope, floor, count, point }); await UserGachaRecModel.createRec(roleId, gachaId, activityId, count, resultList); // 任务 await checkTask(roleId, sid, funcs, TASK_TYPE.GASHA, count, true, {}); let resultRefFreeTime = 0; if(dicGacha.free.count > 0) { resultRefFreeTime = getAfterDateByDay(refFreeTime, dicGacha.free.day); } return resResult(STATUS.SUCCESS, { gachaId, activityId, freeCount, refFreeTime: resultRefFreeTime, count, point, floor, heroes, result: resultList }); } /** * @description 设置心愿单 * @param {{ gachaId: number, hope: { id: number, hid: number }[] }} msg * @param {BackendSession} session * @memberof GachaHandler */ async setHope(msg: { gachaId: number, hope: { id: number, hid: number }[] }, session: BackendSession) { const { gachaId, hope } = msg; const roleId: string = session.get('roleId'); for(let { hid } of hope) { let dicHero = gameData.hero.get(hid); if(!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); if(dicHero.quality != HERO_QUALITY_TYPE.GOLD) { return resResult(STATUS.GACHA_HOPE_NOT_GOLD); } } let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { hope: hope.map(cur => { return {...cur, hasGet: false} }) }) return resResult(STATUS.SUCCESS, { gachaId, hope: userGacha.hope }); } /** * @description 转盘 * @param {{ gachaId: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async drawTurnTable(msg: { gachaId: number }, session: BackendSession) { const { gachaId } = msg; const roleId: string = session.get('roleId'); const roleName: string = session.get('roleName'); const sid: string = session.get('sid'); const serverId: number = session.get('serverId'); let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); let { point, turntable } = userGacha; if(point < RECRUIT.RECRUIT_BONUS_RECRUIT) return resResult(STATUS.GACHA_TURNTABLE_POINT_NOT_ENOUGH); let turntablePool: { quality: number, count: number }[] = []; for(let { quality, count } of gameData.gachaTurntable) { let myTurntable = turntable.find(cur => cur.quality == quality); if(myTurntable && myTurntable.hasGet) { turntablePool.push({ quality, count }); } } if(turntablePool.length <= 0) { // 重置 turntable = []; turntablePool = gameData.gachaTurntable; } let randTurntable = getRandEelm(turntablePool); let { quality, count } = randTurntable[0]; // 根据品质查武将 let pool = getAllHeroByQuality(quality); let hero = getRandEelm(pool); let contentId = gameData.gachaContentHero.get(hero[0]); // 获得或者转成碎片 let heroInfo: { hid: number }[] = []; for(let i = 0; i < count; i++) { heroInfo.push({ hid: hero[0] }) } let { heroes, goods } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); let resultList: GachaResult[] = []; for(let h of heroes) { let result = new GachaResult(contentId); result.setHero(h.hid); resultList.push(result); } for(let g of goods) { let result = new GachaResult(contentId); result.setHero(hero[0]); result.transferToPiece(g.id, g.count); resultList.push(result); } // 记录 let myTurntable = turntable.find(cur => cur.quality == quality); if(!myTurntable) { myTurntable = { quality, hasGet: false }; turntable.push(myTurntable); } myTurntable.hasGet = true; // 扣除积分 userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { point: point - 1, turntable }); return resResult(STATUS.SUCCESS, { gachaId, point: userGacha.point, turntable: userGacha.turntable, result: resultList, heroes, goods }); } /** * @description 求贤若渴&限时招募里面设置pick武将 * @param {{ gachaId: number, pickHero: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async setPickHero(msg: { gachaId: number, activityId: number, pickHero: number }, session: BackendSession) { const { gachaId, activityId, pickHero } = msg; const roleId: string = session.get('roleId'); if(gachaId != GACHA_ID.ASSIGN && gachaId != GACHA_ID.TIMELIMIT) return resResult(STATUS.WRONG_PARMS); let dicHero = gameData.hero.get(pickHero); if(!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); let heroes: number[] = []; if(gachaId == GACHA_ID.TIMELIMIT) { let activityData = await ActivityModel.findActivity(activityId, true); if(!activityData) return resResult(STATUS.ACTIVITY_MISSING); let gachaData = new GachaData(activityData); heroes = gachaData.heroes; if(!heroes.includes(pickHero)) { return resResult(STATUS.GACHA_CAN_NOT_PICK) } } let userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { pickHero }) return resResult(STATUS.SUCCESS, { gachaId, heroes, pickHero: userGacha.pickHero }); } /** * @description 今天拜访过的武将 * @param {{ }} msg * @param {BackendSession} session * @memberof GachaHandler */ async getVisitedHero(msg: { }, session: BackendSession) { const roleId: string = session.get('roleId'); let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL, 0); if(shouldRefresh(refVisitedTime, new Date(), REFRESH_HOUR)) { visitedHero = []; } return resResult(STATUS.SUCCESS, { hids: visitedHero }); } /** * @description 拜访武将 * @param {{ hid: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async visitHero(msg: { hid: number }, session: BackendSession) { const roleId: string = session.get('roleId'); const roleName: string = session.get('roleName'); const sid: string = session.get('sid'); const { hid } = msg; let dicHero = gameData.hero.get(hid); if(!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); if(!dicHero.recruit) return resResult(STATUS.DIC_DATA_NOT_FOUND); let { pieceId } = dicHero; let { visitedHero, refVisitedTime } = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL, 0); if(shouldRefresh(refVisitedTime, new Date(), REFRESH_HOUR)) { visitedHero = []; refVisitedTime = getTodayZeroDate(REFRESH_HOUR); } if(visitedHero.includes(hid)) { return resResult(STATUS.GACHA_HAS_VISITED); } if(visitedHero.length >= RECRUIT.RECRUIT_DAILY_RECRUIT_SHARD) { return resResult(STATUS.GACHA_VISITED_COUNT_OVER); } visitedHero.push(hid); let userGacha = await UserGachaModel.updateInfo(roleId, GACHA_ID.NORMAL, 0, { visitedHero, refVisitedTime }); let goods = await addItems(roleId, roleName, sid, [{ id: pieceId, count: RECRUIT.RECRUIT_SHARD_LIMIT }]); return resResult(STATUS.SUCCESS, { hids: userGacha.visitedHero, goods }); } }