import { Application, BackendSession, HandlerService, } from "pinus"; import { resResult, shouldRefresh, getRandSingleEelm } from "../../../pubUtils/util"; import { STATUS, GACHA_ID, HERO_QUALITY_TYPE, TASK_TYPE, ITEM_CHANGE_REASON, } from "../../../consts"; import { gameData } from "../../../pubUtils/data"; import { GachaResult, GachaData } from "../../../domain/activityField/gachaField"; import { UserGachaModel } from "../../../db/UserGacha"; import { refreshGacha, getGachaList, getVisitedHeroList, getAllHeroByQuality, GachaPull } from "../../../services/activity/gachaService"; import { RoleModel } from "../../../db/Role"; import { HeroModel } from "../../../db/Hero"; import { handleCost, addItems } from "../../../services/role/rewardService"; import { getZeroPointD, getTimeFun } from "../../../pubUtils/timeUtil"; import { UserGachaRecModel } from "../../../db/UserGachaRec"; import { RECRUIT } from "../../../pubUtils/dicParam"; import { getActivityById } from "../../../services/activity/activityService"; import { checkTaskInGacha } from "../../../services/task/taskService"; import { createHeroes } from "../../../services/role/createHero"; import { getRoleCreateTime, getServerCreateTime } from "../../../services/redisService"; export default function (app: Application) { new HandlerService(app, {}); 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 role = await RoleModel.findByRoleId(roleId, 'gachaHasGuide'); const list = await getGachaList(roleId); return resResult(STATUS.SUCCESS, { hasInit: !!role.gachaHasGuide, 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'); 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); userGacha = await refreshGacha(dicGacha, userGacha); let { freeCount, point, pickHero, refFreeTime, count: historyCount } = userGacha; if ((gachaId == GACHA_ID.ASSIGN || gachaId == GACHA_ID.TIMELIMIT) && !pickHero) return resResult(STATUS.GACHA_NOT_ASSIGN); let userHeroes = await HeroModel.findByRole(roleId); let gachaPull = new GachaPull(gachaId); gachaPull.setByUserGacha(dicGacha, userGacha, false); let { resultList, heroInfo, items } = gachaPull.pull(count, userHeroes); let { hope, floor } = gachaPull.getUserGachaParam(); 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, ITEM_CHANGE_REASON.GACHA_PULL); if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); } // 给东西 // console.log('****', heroInfo) let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); // 更新数据 userGacha = await UserGachaModel.updateInfo(roleId, gachaId, activityId, { freeCount, hope, floor, count: historyCount + count }); await UserGachaRecModel.createRec(roleId, gachaId, activityId, count, resultList); await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, false); return resResult(STATUS.SUCCESS, { gachaId, activityId, freeCount, refFreeTime: userGacha.refFreeTime, count: userGacha.count, point: userGacha.point, floor, hope, guideResultCount: userGacha.guideResultCount, // heroes: resultHeroes, addHeros: 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.findByRole(roleId, gachaId); let { hope: userHope = []} = await refreshGacha(gameData.gacha.get(gachaId), userGacha); for (let { id, hid } of hope) { let curHope = userHope.find(cur => cur.id == id); if(curHope) { if(curHope.hasGet) { continue; } else { curHope.hid = hid; curHope.hasGet = false; } } else { userHope.push({ id, hid, hasGet: false }) } } userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { hope: userHope }); 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, 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, resultHeroes, goods } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); let resultList: GachaResult[] = []; for (let h of resultHeroes) { 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, addHeros: heroes, // heroes: resultHeroes }); } /** * @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 getActivityById(activityId); if (!activityData) return resResult(STATUS.ACTIVITY_MISSING); let createTime = await getRoleCreateTime(roleId); let serverTime = await getServerCreateTime(serverId); let gachaData = new GachaData(activityData, createTime, serverTime); 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 = await getVisitedHeroList(roleId); 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); let index = gameData.recruit.findIndex(cur => cur.actorId == hid); if (index == -1) return resResult(STATUS.GACHA_CAN_NOT_PICK); 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 }], ITEM_CHANGE_REASON.VISIT_HERO); return resResult(STATUS.SUCCESS, { hids: userGacha.visitedHero, goods }); } /** * @description 获取特殊抽卡数据 * @param {{}} msg * @param {BackendSession} session * @memberof GachaHandler */ async getGuideGachaData(msg: {}, session: BackendSession) { const { } = msg; const roleId: string = session.get('roleId'); let { gachaHasGuide } = await RoleModel.findByRoleId(roleId, 'gachaHasGuide'); let guideCount = 0, guideResultList = [], candidates = []; if(!gachaHasGuide) { const userGacha = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL); ({ guideCount = 0, guideResultList = [], candidates = [] } = userGacha); } return resResult(STATUS.SUCCESS, { guideCount, latest: guideResultList, candidates }); } /** * @description 预抽卡 * @param {{}} msg * @param {BackendSession} session * @memberof GachaHandler */ async guidePull(msg: {}, session: BackendSession) { const { } = msg; const roleId: string = session.get('roleId'); const sid: string = session.get('sid'); const gachaId = GACHA_ID.NORMAL; const count = 10; const dicGacha = gameData.gacha.get(gachaId); let userGacha = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL); let { guideCount = 0 } = userGacha; if(guideCount >= RECRUIT.RECRUIT_FIRST_RECRUIT) return resResult(STATUS.GACHA_GUIDE_PULL_CNT_LACK); if(guideCount == 0) { // 消耗东西 let cost = dicGacha.cost.map(cur => { return { id: cur.id, count: cur.count * count } }); let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.GACHA_PULL); if (!costResult) return resResult(STATUS.GACHA_COST_NOT_ENOUGH); } let userHeroes = await HeroModel.findByRole(roleId); let gachaPull = new GachaPull(gachaId); gachaPull.setByUserGacha(dicGacha, userGacha, true); let { resultList } = gachaPull.pull(count, userHeroes); userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { guideResultList: resultList, guideCount: guideCount + 1 }) return resResult(STATUS.SUCCESS, { guideCount: userGacha.guideCount, latest: userGacha.guideResultList }); } /** * @description 将结果保存到候选列表 * @param {{ id: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async saveToCandidates(msg: { id: number }, session: BackendSession) { const { id } = msg; const roleId: string = session.get('roleId'); const gachaId = GACHA_ID.NORMAL; let userGacha = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL); let { guideResultList, candidates = [], guideCount } = userGacha; let index = candidates.findIndex(cur => cur.id == id); if(index == -1) { candidates.push({ id, guideCount, list: guideResultList }); } else { candidates[index].list = guideResultList; candidates[index].guideCount = guideCount; } userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { candidates }) return resResult(STATUS.SUCCESS, { candidates: userGacha.candidates }); } /** * @description 确定使用某个结果 * @param {{ id: number }} msg * @param {BackendSession} session * @memberof GachaHandler */ async decide(msg: { id: number }, session: BackendSession) { const { id } = msg; const roleId: string = session.get('roleId'); const roleName: string = session.get('roleName'); const serverId: number = session.get('serverId'); const sid: string = session.get('sid'); const gachaId = GACHA_ID.NORMAL; const count = 10; let role = await RoleModel.findByRoleId(roleId); if(role.gachaHasGuide) { return resResult(STATUS.GACHA_GUIDE_HAS_DONE); } let userGacha = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL); let { guideResultList = [], candidates = [], } = userGacha; let simpleResult: { contentId: number, hid: number }[] = [] if(id == 0) { if(guideResultList.length <= 0) { return resResult(STATUS.GACHA_GUIDE_NOT_DO); } simpleResult = guideResultList; } else { let candidate = candidates.find(cur => cur.id == id); if(!candidate) return resResult(STATUS.WRONG_PARMS); simpleResult = candidate.list; } let userHeroes = await HeroModel.findByRole(roleId); let gachaPull = new GachaPull(gachaId); let { items, heroInfo, resultList } = gachaPull.pullBySimpleResult(simpleResult, userHeroes); userGacha = await UserGachaModel.updateInfo(roleId, gachaId, 0, { guideResultCount: count }); // 给东西 // console.log('****', heroInfo) let { heroes, resultHeroes } = await createHeroes(roleId, roleName, sid, serverId, heroInfo); await addItems(roleId, roleName, sid, items, ITEM_CHANGE_REASON.GACHA_ITEMS); // 更新数据 role = await RoleModel.updateRoleInfo(roleId, { gachaHasGuide: true }); await UserGachaRecModel.createRec(roleId, gachaId, 0, count, resultList); // 任务 await checkTaskInGacha(serverId, roleId, sid, count, resultHeroes, resultList, true); return resResult(STATUS.SUCCESS, { hasInit: !!role.gachaHasGuide, guideResultCount: userGacha.guideResultCount, count: userGacha.count, gachaId, // heroes: resultHeroes, addHeros: heroes, result: resultList }); } }