import { Application, BackendSession } from "pinus"; import { resResult, getRandEelmWithWeight, shouldRefresh, getRandSingleEelm } from "../../../pubUtils/util"; import { STATUS, GACHA_ID, HERO_QUALITY_TYPE, TASK_TYPE, REFRESH_TIME, TIME_OUTPUT_TYPE } 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 } from "../../../db/Hero"; import { RewardInter } from "../../../pubUtils/interface"; import { handleCost, createHeroes, addItems } from "../../../services/rewardService"; import { getZeroPointD, getTimeFun } from "../../../pubUtils/timeUtil"; import { UserGachaRecModel } from "../../../db/UserGachaRec"; import { ActivityModel } from "../../../db/Activity"; import { checkActivityTask, 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"; 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, count: historyCount } = 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 } } = getRandEelmWithWeight(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, count: 1 })//默认1个英雄 } } else { items.push({ id: result.id, count: result.count }); } resultList.push(result); } let costNum = count; if (count == 1 && 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, funcs, heroInfo); await addItems(roleId, roleName, sid, items); // 更新数据 userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { freeCount, hope, floor, count: historyCount + count }); await UserGachaRecModel.createRec(roleId, gachaId, activityId, count, resultList); // 任务 await checkTask(roleId, sid, funcs, TASK_TYPE.GASHA, count, true, {}); //活动统计 await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.GASHA, count) let resultRefFreeTime = 0; if (dicGacha.free.count > 0) { let f = getTimeFun(userGacha.refFreeTime); resultRefFreeTime = f.getAfterDayWithHour(dicGacha.free.day); } return resResult(STATUS.SUCCESS, { gachaId, activityId, freeCount, refFreeTime: resultRefFreeTime, count: userGacha.count, point: userGacha.point, floor, hope, 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 (hid != 0) { if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); if (hid != 0 && 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'); const funcs: number[] = session.get('funcs'); let userGacha = await UserGachaModel.findByRole(roleId, gachaId, 0); let { point, turntable, costPoint } = 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 = getRandSingleEelm(turntablePool); let { quality, count } = randTurntable; // 根据品质查武将 let pool = getAllHeroByQuality(quality); let hero = getRandSingleEelm(pool); let contentId = gameData.gachaContentHero.get(hero); // 获得或者转成碎片 let heroInfo: { hid: number, count: number }[] = []; for (let i = 0; i < count; i++) { heroInfo.push({ hid: hero, count: 1 }) } let { heroes, goods } = await createHeroes(roleId, roleName, sid, serverId, funcs, 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); 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, { turntable, costPoint: costPoint + 1 }); return resResult(STATUS.SUCCESS, { gachaId, point: userGacha.point, turntable: userGacha.turntable, result: resultList, heroes }); } /** * @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 = 0, pickHero } = msg; const roleId: string = session.get('roleId'); const serverId: number = session.get('serverId'); 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); 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, activityId, 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())) { 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())) { visitedHero = []; refVisitedTime = getZeroPointD(); } 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 }); } }