Files
ZYZ/game-server/app/servers/activity/handler/gachaHandler.ts
2022-05-18 17:02:40 +08:00

479 lines
19 KiB
TypeScript

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 { 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);
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, lv, userHeroes);
gachaPull.setByUserGacha(dicGacha, userGacha);
let { items, heroInfo, resultList, activityData } = gachaPull.pull(count);
let { hope, floor } = gachaPull.getUserGachaParam(userGacha);
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');
const userGacha = await UserGachaModel.findByRole(roleId, GACHA_ID.NORMAL);
let { 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, 0, userHeroes);
gachaPull.setByUserGacha({...dicGacha, floorReward: 0}, userGacha);
let { resultList } = gachaPull.pull(count);
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 { lv } = await RoleModel.findByRoleId(roleId);
let userHeroes = await HeroModel.findByRole(roleId);
let gachaPull = new GachaPull(gachaId, lv, userHeroes);
let { items, heroInfo, resultList, activityData } = gachaPull.pullBySimpleResult(simpleResult);
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
});
}
}