This commit is contained in:
xy
2026-03-13 01:38:40 +00:00
parent e6e4f88257
commit 28855885cd
311 changed files with 89544 additions and 94350 deletions
@@ -1,55 +1,56 @@
import { Application, BackendSession } from "pinus";
import { ScriptBarrageModel } from "../../../db/ScriptBarrage";
import { BarrageReturn } from '../../../domain/roleField/barrage';
import { resResult, getRandEelm } from "../../../pubUtils/util";
import { STATUS } from "../../../consts";
import { closeScriptBarrage } from "../../../pubUtils/sdkUtil";
export default function(app: Application) {
return new BarrageHandler(app);
}
export class BarrageHandler {
constructor(private app: Application) {
}
public async sendBarrage(msg: { warId: number, rid: string, index: string, content: string }, session: BackendSession) {
if(closeScriptBarrage()) return resResult(STATUS.FUNCTION_CLOSE);
const roleId: string = session.get('roleId');
const { warId, rid, index, content } = msg;
const result = await ScriptBarrageModel.createBarrage(roleId, warId, rid, index, content);
let barrageList: BarrageReturn[] = [];
let bs = new BarrageReturn(result);
barrageList.push(bs);
return resResult(STATUS.SUCCESS, { barrageList });
}
public async getBarrageList(msg: {rid: string}, session: BackendSession) {
if(closeScriptBarrage()) return resResult(STATUS.SUCCESS, { barrageList: [] });
// const roleId: string = session.get('roleId');
const { rid } = msg;
const result = await ScriptBarrageModel.getBarrageList(rid, 1000);
const perMax = 10, max = 50; // 每个对话最大数量,每个剧本最大数量
let map = new Map<string, BarrageReturn[]>(); // index => BarrageReturn[]
for(let barrage of result) {
let { index } = barrage;
if(!map.has(index)) {
map.set(index, []);
}
map.get(index).push(new BarrageReturn(barrage));
}
let ratio = result.length > max? max/result.length: 1;
let barrageList: BarrageReturn[] = [];
for(let [_, barrages] of map) {
let count = Math.ceil(barrages.length * ratio);
if(count > perMax) count = perMax;
let curBarrages = getRandEelm(barrages, count);
barrageList = barrageList.concat(curBarrages);
}
return resResult(STATUS.SUCCESS, { barrageList });
}
}
import { Application, BackendSession } from "pinus";
import { ScriptBarrageModel } from "@db/ScriptBarrage";
import { BarrageReturn } from '@domain/roleField/barrage';
import { resResult, getRandEelm } from "@pubUtils/util";
import { STATUS } from "../../../consts";
import { closeScriptBarrage } from "@pubUtils/sdkUtil";
export default function(app: Application) {
return new BarrageHandler(app);
}
export class BarrageHandler {
constructor(private app: Application) {
}
public async sendBarrage(msg: { warId: number, rid: string, index: string, content: string }, session: BackendSession) {
if(closeScriptBarrage()) return resResult(STATUS.FUNCTION_CLOSE);
const roleId: string = session.get('roleId');
const { warId, rid, index, content } = msg;
const result = await ScriptBarrageModel.createBarrage(roleId, warId, rid, index, content);
let barrageList: BarrageReturn[] = [];
let bs = new BarrageReturn(result);
barrageList.push(bs);
return resResult(STATUS.SUCCESS, { barrageList });
}
public async getBarrageList(msg: {rid: string}, session: BackendSession) {
if(closeScriptBarrage()) return resResult(STATUS.SUCCESS, { barrageList: [] });
// const roleId: string = session.get('roleId');
const { rid } = msg;
const result = await ScriptBarrageModel.getBarrageList(rid, 1000);
const perMax = 10, max = 50; // 每个对话最大数量,每个剧本最大数量
let map = new Map<string, BarrageReturn[]>(); // index => BarrageReturn[]
for(let barrage of result) {
let { index } = barrage;
if(!map.has(index)) {
map.set(index, []);
}
map.get(index).push(new BarrageReturn(barrage));
}
let ratio = result.length > max? max/result.length: 1;
let barrageList: BarrageReturn[] = [];
for(let [_, barrages] of map) {
let count = Math.ceil(barrages.length * ratio);
if(count > perMax) count = perMax;
let curBarrages = getRandEelm(barrages, count);
barrageList = barrageList.concat(curBarrages);
}
return resResult(STATUS.SUCCESS, { barrageList });
}
}
@@ -1,70 +1,71 @@
import { Application, BackendSession } from 'pinus';
import { DailyRecordModel } from '../../../db/DailyRecord';
import { STATUS } from '../../../consts/statusCode';
import { resResult } from '../../../pubUtils/util';
import { RoleModel } from '../../../db/Role';
import { getDailyNum, getDailyBattleList, getDailyBuyCountCost } from '../../../services/dailyBattleService';
import { getGoldObject, handleCost } from '../../../services/role/rewardService';
import { gameData } from '../../../pubUtils/data';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts';
export default function(app: Application) {
return new DailyBattleHandler(app);
}
export class DailyBattleHandler {
constructor(private app: Application) {
}
// 获取关卡列表
async getData(msg: { }, session: BackendSession) {
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let result = await getDailyBattleList(role);
return resResult(STATUS.SUCCESS, { list: result });
}
// 购买每日次数
async buyNum(msg: { type: number, count: number }, session: BackendSession) {
let {type, count} = msg;
if( !count || count < 0) return resResult(STATUS.WRONG_PARMS);
const roleId = session.get('roleId');
const sid = session.get('sid');
const curDaily = gameData.daily.find(cur => cur.dailyType == type);
if(!curDaily) return resResult(STATUS.DAILY_TYPE_NOT_FOUND);
let { buyCount = 0 } = await DailyRecordModel.refreshRecord(roleId, type);
if(buyCount + count > curDaily.timesCanBuy ) {
return resResult(STATUS.DAILY_REFRESH_TIMES_LACK)
}
let buyCost = 0;
for(let i = 1; i <= count; i++) {
let num = buyCount + i;
buyCost += getDailyBuyCountCost(num);
}
let role = await RoleModel.findByRoleId(roleId);
if(buyCost > role.gold) {
return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
}
await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DAILY_BATTLE_BUY_CNT);
let newDailyRecord = await DailyRecordModel.increseBuyCount(roleId, type, count);
let checkDailyResult = await getDailyNum(newDailyRecord, role);
return resResult(STATUS.SUCCESS, { type, ...checkDailyResult, buyCost});
}
async debugResetNum(msg: { magicWord: string, type: number }, session: BackendSession) {
const { magicWord, type } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await DailyRecordModel.deleteAccount(roleId);
return resResult(STATUS.SUCCESS);
}
}
import { Application, BackendSession } from 'pinus';
import { DailyRecordModel } from '@db/DailyRecord';
import { STATUS } from '@consts/statusCode';
import { resResult } from '@pubUtils/util';
import { RoleModel } from '@db/Role';
import { getDailyNum, getDailyBattleList, getDailyBuyCountCost } from '../../../services/dailyBattleService';
import { getGoldObject, handleCost } from '../../../services/role/rewardService';
import { gameData } from '@pubUtils/data';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts';
export default function(app: Application) {
return new DailyBattleHandler(app);
}
export class DailyBattleHandler {
constructor(private app: Application) {
}
// 获取关卡列表
async getData(msg: { }, session: BackendSession) {
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let result = await getDailyBattleList(role);
return resResult(STATUS.SUCCESS, { list: result });
}
// 购买每日次数
async buyNum(msg: { type: number, count: number }, session: BackendSession) {
let {type, count} = msg;
if( !count || count < 0) return resResult(STATUS.WRONG_PARMS);
const roleId = session.get('roleId');
const sid = session.get('sid');
const curDaily = gameData.daily.find(cur => cur.dailyType == type);
if(!curDaily) return resResult(STATUS.DAILY_TYPE_NOT_FOUND);
let { buyCount = 0 } = await DailyRecordModel.refreshRecord(roleId, type);
if(buyCount + count > curDaily.timesCanBuy ) {
return resResult(STATUS.DAILY_REFRESH_TIMES_LACK)
}
let buyCost = 0;
for(let i = 1; i <= count; i++) {
let num = buyCount + i;
buyCost += getDailyBuyCountCost(num);
}
let role = await RoleModel.findByRoleId(roleId);
if(buyCost > role.gold) {
return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
}
await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DAILY_BATTLE_BUY_CNT);
let newDailyRecord = await DailyRecordModel.increseBuyCount(roleId, type, count);
let checkDailyResult = await getDailyNum(newDailyRecord, role);
return resResult(STATUS.SUCCESS, { type, ...checkDailyResult, buyCost});
}
async debugResetNum(msg: { magicWord: string, type: number }, session: BackendSession) {
const { magicWord, type } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await DailyRecordModel.deleteAccount(roleId);
return resResult(STATUS.SUCCESS);
}
}
@@ -1,87 +1,88 @@
import { Application, BackendSession } from 'pinus';
import { STATUS } from '../../../consts/statusCode';
import { resResult, shouldRefresh } from '../../../pubUtils/util';
import { RoleModel } from '../../../db/Role';
import { getGoldObject, handleCost } from '../../../services/role/rewardService';
import { getDungeonData, getDungeonBuyCountCost } from '../../../services/dungeonService';
import * as dicParam from '../../../pubUtils/dicParam';
import { DungeonFirstModel } from '../../../db/DungeonFirst';
import { DungeonResultParam } from '../../../domain/battleField/dungeon';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts';
import { getVipDungeonCnt } from '../../../services/activity/monthlyTicketService';
export default function(app: Application) {
return new DungeonBattleHandler(app);
}
export class DungeonBattleHandler {
constructor(private app: Application) {
}
// 获取关卡列表
async getData(msg: { }, session: BackendSession) {
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let res = await getDungeonData(role);
return resResult(STATUS.SUCCESS, res);
}
// 购买每日次数
async buyNum(msg: { count: number }, session: BackendSession) {
let { count } = msg;
const roleId = session.get('roleId');
const sid = session.get('sid');
let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime } = await RoleModel.findByRoleId(roleId);
let curTime = new Date();
let needRefresh = shouldRefresh(dungeonRefTime, curTime);
if(needRefresh) {
dungeonCnt = 0; dungeonBuyCnt = 0;
}
let timesCanBuy = dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY;
if(dungeonBuyCnt + count > timesCanBuy ) {
return resResult(STATUS.DUNGEON_REFRESH_TIMES_LACK)
}
let buyCost = 0;
for(let i = 1; i <= count; i++) {
buyCost += getDungeonBuyCountCost(dungeonBuyCnt + i);
}
let {gold} = await RoleModel.findByRoleId(roleId);
if(buyCost > gold) {
return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
}
await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DUNGEON_BATTLE_BUY_CNT);
await RoleModel.buyCnt(roleId, needRefresh, count, curTime);
let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + count + 1);
let freeCount = getVipDungeonCnt(session.get('vipStartTime'));
return resResult(STATUS.SUCCESS, {
costGold: buyCost,
nextCostGold,
battleCount: freeCount + dungeonBuyCnt + count - dungeonCnt,
buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - count
});
}
// 购买每日次数
async getFirstInfo(msg: { movePoint: number }, session: BackendSession) {
const { movePoint } = msg;
const serverId: number = session.get('serverId');
const firstInfos = await DungeonFirstModel.findByMovePoint(serverId, movePoint);
let result: DungeonResultParam[] = firstInfos.map(firstInfo => {
return new DungeonResultParam(firstInfo);
});
return resResult(STATUS.SUCCESS, { infos: result });
}
async debugResetRefTime(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await RoleModel.updateRoleInfo(roleId, { dungeonRefTime: new Date(Date.now() - 86400000) });
return resResult(STATUS.SUCCESS);
}
}
import { Application, BackendSession } from 'pinus';
import { STATUS } from '@consts/statusCode';
import { resResult, shouldRefresh } from '@pubUtils/util';
import { RoleModel } from '@db/Role';
import { getGoldObject, handleCost } from '../../../services/role/rewardService';
import { getDungeonData, getDungeonBuyCountCost } from '../../../services/dungeonService';
import * as dicParam from '@pubUtils/dicParam';
import { DungeonFirstModel } from '@db/DungeonFirst';
import { DungeonResultParam } from '@domain/battleField/dungeon';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON } from '../../../consts';
import { getVipDungeonCnt } from '../../../services/activity/monthlyTicketService';
export default function(app: Application) {
return new DungeonBattleHandler(app);
}
export class DungeonBattleHandler {
constructor(private app: Application) {
}
// 获取关卡列表
async getData(msg: { }, session: BackendSession) {
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let res = await getDungeonData(role);
return resResult(STATUS.SUCCESS, res);
}
// 购买每日次数
async buyNum(msg: { count: number }, session: BackendSession) {
let { count } = msg;
const roleId = session.get('roleId');
const sid = session.get('sid');
let { dungeonCnt = 0, dungeonBuyCnt = 0, dungeonRefTime } = await RoleModel.findByRoleId(roleId);
let curTime = new Date();
let needRefresh = shouldRefresh(dungeonRefTime, curTime);
if(needRefresh) {
dungeonCnt = 0; dungeonBuyCnt = 0;
}
let timesCanBuy = dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY;
if(dungeonBuyCnt + count > timesCanBuy ) {
return resResult(STATUS.DUNGEON_REFRESH_TIMES_LACK)
}
let buyCost = 0;
for(let i = 1; i <= count; i++) {
buyCost += getDungeonBuyCountCost(dungeonBuyCnt + i);
}
let {gold} = await RoleModel.findByRoleId(roleId);
if(buyCost > gold) {
return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
}
await handleCost(roleId, sid, [getGoldObject(buyCost)], ITEM_CHANGE_REASON.DUNGEON_BATTLE_BUY_CNT);
await RoleModel.buyCnt(roleId, needRefresh, count, curTime);
let nextCostGold = getDungeonBuyCountCost(dungeonBuyCnt + count + 1);
let freeCount = getVipDungeonCnt(session.get('vipStartTime'));
return resResult(STATUS.SUCCESS, {
costGold: buyCost,
nextCostGold,
battleCount: freeCount + dungeonBuyCnt + count - dungeonCnt,
buyCount: dicParam.DUNGEON_CONST.DUNGEON_CONST_BUY - dungeonBuyCnt - count
});
}
// 购买每日次数
async getFirstInfo(msg: { movePoint: number }, session: BackendSession) {
const { movePoint } = msg;
const serverId: number = session.get('serverId');
const firstInfos = await DungeonFirstModel.findByMovePoint(serverId, movePoint);
let result: DungeonResultParam[] = firstInfos.map(firstInfo => {
return new DungeonResultParam(firstInfo);
});
return resResult(STATUS.SUCCESS, { infos: result });
}
async debugResetRefTime(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await RoleModel.updateRoleInfo(roleId, { dungeonRefTime: new Date(Date.now() - 86400000) });
return resResult(STATUS.SUCCESS);
}
}
@@ -1,161 +1,162 @@
import { Application, BackendSession, HandlerService, } from 'pinus';
import { EventRecordModel } from '../../../db/EventRecord';
import { RoleModel } from '../../../db/Role';
import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_ANSWER_STATUS, TASK_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, EVENT_TYPE, EVENT_QUIZ_NUM } from '../../../consts';
import { checkEventStatus, getEventSuccessStatus, getEvent, checkQuiz, startEvent, refreshEvent, getEventTime, randomPosition, randomQuestion } from '../../../services/eventSercive';
import { addItems } from '../../../services/role/rewardService';
import { STATUS } from '../../../consts/statusCode';
import { genCode, resResult } from '../../../pubUtils/util';
import { checkTask } from '../../../services/task/taskService';
import { gameData } from '../../../pubUtils/data';
export default function (app: Application) {
new HandlerService(app, {});
return new EventBattleHandler(app);
}
export class EventBattleHandler {
constructor(private app: Application) {
}
// 主动获取奇遇事件
async getEvents(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let eventStatus = session.get('eventStatus');
let event = eventStatus == EVENT_STATUS.WAITING? await startEvent(session): await getEvent(eventStatus, roleId, roleName);
return resResult(STATUS.SUCCESS, { list: event });
}
// 回答问题
async checkAnswer(msg: { eventId: number, eventCode: string, questionId: number, answer: number }, session: BackendSession) {
const { eventId, eventCode, questionId, answer } = msg;
let roleId = session.get('roleId');
// let roleName = session.get('roleName');
// let eventStatus = session.get('eventStatus');
let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode);
if (!event) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { status, type, eventId: dataEventId, question } = event;
if (status != EVENT_RECORD_STATUS.WAITING) {
return resResult(STATUS.EVENT_STATUS_ERROR);
}
if (dataEventId != eventId) {
return resResult(STATUS.EVENT_WRONG_ID);
}
let curQuestion = question.find(cur => cur.id == questionId);
if (!curQuestion) return resResult(STATUS.EVENT_QUESTION_NOT_FOUND);
let { isCorrect, answerNo } = checkQuiz(questionId, answer);
let result = await EventRecordModel.saveEventAnswer(eventCode, questionId, isCorrect ? EVENT_ANSWER_STATUS.CORRECT : EVENT_ANSWER_STATUS.WRONG);
if (!result) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { question: newQuestion } = result;
let isClear = true, allCorrect = true;
for (let { status } of newQuestion) {
if (status) {
if (status == EVENT_ANSWER_STATUS.WRONG) {
allCorrect = false;
}
} else {
isClear = false; allCorrect = false;
}
}
if (isClear) {
await EventRecordModel.setStatusByCode(roleId, eventCode, allCorrect ? EVENT_RECORD_STATUS.BATTLE_SUCCESS : EVENT_RECORD_STATUS.BATTLE_FAIL);
}
return resResult(STATUS.SUCCESS, { eventCode, eventId, questionId, isCorrect, answerNo });
}
// 获取关卡列表
async receiveEventReward(msg: { eventId: number, eventCode: string }, session: BackendSession) {
const { eventId, eventCode } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let eventStatus = session.get('eventStatus');
let sid = session.get('sid');
const serverId = session.get('serverId');
let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode);
if (!event) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { status, type, eventId: dataEventId, question } = event;
let flag = checkEventStatus(type, status);
if (!flag) {
return resResult(STATUS.EVENT_STATUS_ERROR);
}
let checkResult = getEventSuccessStatus(type, status, question);
if (checkResult.status == -1) {
return resResult(STATUS.EVENT_QUESTION_NO_ANSWER);
}
let isSuccess = checkResult.isSuccess;
if (dataEventId != eventId) {
return resResult(STATUS.EVENT_WRONG_ID);
}
let dicEvent = gameData.event.get(eventId);
if (!dicEvent) {
return resResult(STATUS.EVENT_INFO_NOT_FOUND);
}
// 保存状态
let result = await EventRecordModel.setStatusByCode(roleId, eventCode, isSuccess ? EVENT_RECORD_STATUS.SUCCESS_RECEIVED : EVENT_RECORD_STATUS.FAIL_RECEIVED);
// 保存奖励
let reward = isSuccess ? dicEvent.winReward : dicEvent.loseReward;
let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.EVENT_REWARD);
if (eventStatus == EVENT_STATUS.STARTING) { // 如果是第一次开启的挑战,保存成开启状态
await RoleModel.setEventStatus(roleId, EVENT_STATUS.OPEN);
// 第一场时间挑战完,开始正常刷新事件,所以刷新时间也重置起来
session.set('eventStatus', EVENT_STATUS.OPEN);
session.push('eventStatus', () => { });
}
// 推送消息刷新
// await checkEvent(session, true);
// 任务
await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EVENT, { eventType: dicEvent.eventType });
return resResult(STATUS.SUCCESS, {
isSuccess,
eventCode: result.eventCode,
eventId: result.eventId,
status: result.status,
goods
});
}
async debugRefEvent(msg: { magicWord: string, eventId: number }, session: BackendSession) {
const { magicWord, eventId } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let now = new Date();
let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18
await EventRecordModel.updateMany({ roleId }, { $set: {status: -1} });
let dic = gameData.event.get(eventId);
let point = randomPosition(dic.movePointArray, [], []);
if(!point) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined;
let eventCode = genCode(8);
await EventRecordModel.saveEventRecord(eventCode, {
roleId, refTime: curTime, eventId: dic.eventID,
roleName, turn: 1, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality,
status: EVENT_RECORD_STATUS.WAITING,
point, question
});
return resResult(STATUS.SUCCESS);
}
}
import { Application, BackendSession, HandlerService, } from 'pinus';
import { EventRecordModel } from '@db/EventRecord';
import { RoleModel } from '@db/Role';
import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_ANSWER_STATUS, TASK_TYPE, DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, EVENT_TYPE, EVENT_QUIZ_NUM } from '../../../consts';
import { checkEventStatus, getEventSuccessStatus, getEvent, checkQuiz, startEvent, refreshEvent, getEventTime, randomPosition, randomQuestion } from '../../../services/eventSercive';
import { addItems } from '../../../services/role/rewardService';
import { STATUS } from '@consts/statusCode';
import { genCode, resResult } from '@pubUtils/util';
import { checkTask } from '../../../services/task/taskService';
import { gameData } from '@pubUtils/data';
export default function (app: Application) {
new HandlerService(app, {});
return new EventBattleHandler(app);
}
export class EventBattleHandler {
constructor(private app: Application) {
}
// 主动获取奇遇事件
async getEvents(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let eventStatus = session.get('eventStatus');
let event = eventStatus == EVENT_STATUS.WAITING? await startEvent(session): await getEvent(eventStatus, roleId, roleName);
return resResult(STATUS.SUCCESS, { list: event });
}
// 回答问题
async checkAnswer(msg: { eventId: number, eventCode: string, questionId: number, answer: number }, session: BackendSession) {
const { eventId, eventCode, questionId, answer } = msg;
let roleId = session.get('roleId');
// let roleName = session.get('roleName');
// let eventStatus = session.get('eventStatus');
let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode);
if (!event) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { status, type, eventId: dataEventId, question } = event;
if (status != EVENT_RECORD_STATUS.WAITING) {
return resResult(STATUS.EVENT_STATUS_ERROR);
}
if (dataEventId != eventId) {
return resResult(STATUS.EVENT_WRONG_ID);
}
let curQuestion = question.find(cur => cur.id == questionId);
if (!curQuestion) return resResult(STATUS.EVENT_QUESTION_NOT_FOUND);
let { isCorrect, answerNo } = checkQuiz(questionId, answer);
let result = await EventRecordModel.saveEventAnswer(eventCode, questionId, isCorrect ? EVENT_ANSWER_STATUS.CORRECT : EVENT_ANSWER_STATUS.WRONG);
if (!result) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { question: newQuestion } = result;
let isClear = true, allCorrect = true;
for (let { status } of newQuestion) {
if (status) {
if (status == EVENT_ANSWER_STATUS.WRONG) {
allCorrect = false;
}
} else {
isClear = false; allCorrect = false;
}
}
if (isClear) {
await EventRecordModel.setStatusByCode(roleId, eventCode, allCorrect ? EVENT_RECORD_STATUS.BATTLE_SUCCESS : EVENT_RECORD_STATUS.BATTLE_FAIL);
}
return resResult(STATUS.SUCCESS, { eventCode, eventId, questionId, isCorrect, answerNo });
}
// 获取关卡列表
async receiveEventReward(msg: { eventId: number, eventCode: string }, session: BackendSession) {
const { eventId, eventCode } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let eventStatus = session.get('eventStatus');
let sid = session.get('sid');
const serverId = session.get('serverId');
let event = await EventRecordModel.getEventRecordByCode(roleId, eventCode);
if (!event) {
return resResult(STATUS.EVENT_RECORD_NOT_FOUND);
}
let { status, type, eventId: dataEventId, question } = event;
let flag = checkEventStatus(type, status);
if (!flag) {
return resResult(STATUS.EVENT_STATUS_ERROR);
}
let checkResult = getEventSuccessStatus(type, status, question);
if (checkResult.status == -1) {
return resResult(STATUS.EVENT_QUESTION_NO_ANSWER);
}
let isSuccess = checkResult.isSuccess;
if (dataEventId != eventId) {
return resResult(STATUS.EVENT_WRONG_ID);
}
let dicEvent = gameData.event.get(eventId);
if (!dicEvent) {
return resResult(STATUS.EVENT_INFO_NOT_FOUND);
}
// 保存状态
let result = await EventRecordModel.setStatusByCode(roleId, eventCode, isSuccess ? EVENT_RECORD_STATUS.SUCCESS_RECEIVED : EVENT_RECORD_STATUS.FAIL_RECEIVED);
// 保存奖励
let reward = isSuccess ? dicEvent.winReward : dicEvent.loseReward;
let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.EVENT_REWARD);
if (eventStatus == EVENT_STATUS.STARTING) { // 如果是第一次开启的挑战,保存成开启状态
await RoleModel.setEventStatus(roleId, EVENT_STATUS.OPEN);
// 第一场时间挑战完,开始正常刷新事件,所以刷新时间也重置起来
session.set('eventStatus', EVENT_STATUS.OPEN);
session.push('eventStatus', () => { });
}
// 推送消息刷新
// await checkEvent(session, true);
// 任务
await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EVENT, { eventType: dicEvent.eventType });
return resResult(STATUS.SUCCESS, {
isSuccess,
eventCode: result.eventCode,
eventId: result.eventId,
status: result.status,
goods
});
}
async debugRefEvent(msg: { magicWord: string, eventId: number }, session: BackendSession) {
const { magicWord, eventId } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let now = new Date();
let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18
await EventRecordModel.updateMany({ roleId }, { $set: {status: -1} });
let dic = gameData.event.get(eventId);
let point = randomPosition(dic.movePointArray, [], []);
if(!point) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined;
let eventCode = genCode(8);
await EventRecordModel.saveEventRecord(eventCode, {
roleId, refTime: curTime, eventId: dic.eventID,
roleName, turn: 1, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality,
status: EVENT_RECORD_STATUS.WAITING,
point, question
});
return resResult(STATUS.SUCCESS);
}
}
@@ -1,420 +1,421 @@
import { Application, BackendSession, HandlerService, } from 'pinus';
import { BattleRecordModel } from '../../../db/BattleRecord';
import { ExpeditionRecordModel } from '../../../db/ExpeditionRecord';
import { ExpeditionWarRecordModel } from '../../../db/ExpeditionWarRecord';
import { ExpeditionPointModel } from '../../../db/ExpeditionPoint';
import { RoleModel } from '../../../db/Role';
import { genCode, getWarTypeName } from '../../../pubUtils/util';
import { getPointRewardStatus, getResetRemainCnt, findOrCreateEnemies, getExpeditionStatus } from '../../../services/expeditionService';
import { DEBUG_MAGIC_WORD, EXPEDITION_WAR_RECORD_STATUS, ITEM_CHANGE_REASON, KING_EXP_RATIO_TYPE, TASK_TYPE, TA_EVENT } from '../../../consts';
import { WarReward } from '../../../services/warRewardService';
import { addItems } from '../../../services/role/rewardService';
import { getAp, setAp } from '../../../services/actionPointService';
import { STATUS } from '../../../consts/statusCode';
import { resResult } from '../../../pubUtils/util';
import { calculateWarStar, checkBattleHeroes, getBattleRecordParam, roleLevelup } from '../../../services/normalBattleService';
import { checkTask, checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInSkipExpedition } from '../../../services/task/taskService';
import { gameData } from '../../../pubUtils/data';
import * as dicParam from '../../../pubUtils/dicParam';
import { getSeconds, nowSeconds } from '../../../pubUtils/timeUtil';
import { reportTAEvent } from '../../../services/sdkService';
import { getSumCe } from '../../../services/playerCeService';
import { vipCanSkipExpedition } from '../../../services/activity/monthlyTicketService';
import { isHeroHidden } from '../../../services/dataService';
import { pvpEndParamInter } from '../../../pubUtils/interface';
export default function (app: Application) {
new HandlerService(app, {});
return new ExpeditionBattleHandler(app);
}
export class ExpeditionBattleHandler {
constructor(private app: Application) {
}
/**
* 获取初始数据
* 获取当前远征挑战情况,远征点数,点数宝箱领取情况 */
async getStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let res = await getExpeditionStatus(roleId, roleName);
if (!res) return resResult(STATUS.ROLE_IS_NOT_INIT);
return resResult(STATUS.SUCCESS, res);
}
/**
* 重置远征本
* 每天5点可以重置远征本 */
async resetStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let curTime = new Date();
let { needRefresh, resetCnt } = await getResetRemainCnt(curTime, roleId);
if (resetCnt <= 0) {
return resResult(STATUS.EXPEDITION_RESET_NUM_NOT_ENOUGH)
}
await ExpeditionRecordModel.hideRecord(roleId); // 刷掉旧关卡
// 我方战力
let myCe = await getSumCe(roleId);
// 每一关的挑战状态
let { expeditionCode, heroes } = await ExpeditionRecordModel.createRecord({
roleId, roleName, heroes: [], myCe
});
await findOrCreateEnemies(roleId, myCe, expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
await RoleModel.increaseExpeditionResetCnt(roleId, needRefresh, curTime);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode);
let curLv = 0;
if (expeditionWarRecord.length > 0) {
curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId;
}
return resResult(STATUS.SUCCESS, {
expeditionCode,
curLv,
expeditionWarRecord,
heroes,
resetCnt: resetCnt - 1
});
}
/**
* 获取敌军数据
* 匹配其他玩家,或机器人数据
*/
async getEnemies(msg: { expeditionCode: string, expeditionId: number }, session: BackendSession) {
const roleId = session.get('roleId');
// const roleName = session.get('roleName');
const { expeditionCode, expeditionId } = msg;
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (expeditionWarRecord && (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS)) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
let { myCe } = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let curExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING);
if (!curExpeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MATCH_NO_PLAYER);
}
let { battleId, mapseid, enemyFrom, enemies, battleStatus, ce: curCe } = curExpeditionWarRecord;
let nextCe = 0; // 下一关战力
if (gameData.expedition.has(expeditionId + 1)) {
let nextExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.HIDE);
if (nextExpeditionWarRecord) nextCe = nextExpeditionWarRecord.ce;
}
return resResult(STATUS.SUCCESS, {
expeditionCode, expeditionId, battleId, mapseid,
battleStatus,
enemyFrom,
enemies,
curCe,
nextCe
});
}
/**
* 进入战斗
* 记录我军数据,生成战斗唯一表示,记录状态
*/
async checkBattle(msg: { expeditionCode: string, expeditionId: number, battleId: number, heroes: number[] }, session: BackendSession) {
const { expeditionCode, expeditionId, battleId, heroes: seqIds = [] } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let ip = session.get('ip');
let serverId = session.get('serverId');
let sid = session.get('sid');
let warInfo = gameData.war.get(battleId);
if (!warInfo) {
return resResult(STATUS.BATTLE_MISS_INFO);
}
let role = await RoleModel.findByRoleId(roleId, 'lv warStar');
let apJson = await getAp(roleId, ip, role.lv);
let { ap } = apJson;
if (ap < warInfo.cost) {
return resResult(STATUS.BATTLE_ACTION_POINT_LACK);
}
// 前置关卡是否挑战过
let previousGk = warInfo.previousGk;
if (previousGk) {
let preBattle = role.warStar.findIndex(cur => cur.id == previousGk);
if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK);
}
let { isOK, hids } = await checkBattleHeroes(roleId, seqIds);
if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
if (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
const battleCode = genCode(8);
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: {
roleId, roleName, battleId,
status: 0,
warName: warInfo.gk_name,
warType: warInfo.warType,
record: { heroes: hids, seqIds }
}
}, true);
let result = await ExpeditionWarRecordModel.updateBattleCode(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING, battleCode);
await checkTaskInBattleStart(serverId, roleId, sid, battleId);
return resResult(STATUS.SUCCESS, {
expeditionCode,
expeditionId,
battleId,
battleCode,
battleStatus: result.battleStatus
});
}
/**
* 跳过
*/
async skipExpedition(msg: { expeditionCode: string, expeditionId: number, battleId: number }, session: BackendSession) {
const { expeditionCode, expeditionId, battleId } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let dicExpedition = gameData.expedition.get(expeditionId);
if(dicExpedition.warId != battleId) return resResult(STATUS.WRONG_PARMS);
let dicWar = gameData.war.get(battleId);
if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND);
// 前置关卡是否挑战过
let role = await RoleModel.findByRoleId(roleId, 'warStar topLineupCe vipStartTime')
let { warStar, topLineupCe, vipStartTime } = role;
let previousGk = dicWar.previousGk;
if (previousGk) {
let preBattle = warStar.findIndex(cur => cur.id == previousGk);
if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK);
}
// 检查record
let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionRecord || !expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
if(expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
// 检查战力是否足够
if(!vipCanSkipExpedition(expeditionWarRecord.ce, topLineupCe, vipStartTime)) {
return resResult(STATUS.EXPEDITION_SKIP_POWER_NOT_ENOUGH)
}
// 更新敌人剩余状态及战斗状态
expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.SUCCESS, []);
// 更新点数
role = await RoleModel.increaseExpeditionPoint(roleId, dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS);
// 关卡奖励
let warReward = new WarReward(roleId, roleName, sid, battleId, true);
let reward = await warReward.saveReward(1);
let curWarStar = warStar.find(cur => cur.id == battleId);
let { newWarStars, newStar } = calculateWarStar(warStar, battleId, []);
if (!curWarStar || newStar > curWarStar.star) {
role = await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars });
}
// 更新下一关状态
if (gameData.expedition.has(expeditionId + 1)) {
await findOrCreateEnemies(roleId, expeditionRecord.myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
}
await checkTaskInSkipExpedition(serverId, roleId, sid, battleId);
return resResult(STATUS.SUCCESS, {
expeditionCode,
expeditionId,
battleId,
goods: reward,
expeditionPoint: role.expeditionPoint
});
}
/**
* 战斗结算
* 结算战斗奖励,更新远征状态
*/
async battleEnd(msg: { expeditionCode: string, expeditionId: number, battleCode: string, battleId: number, isSuccess: boolean, heroes: Array<{ dataId: number, hp: number, ap: number, shield: number, others: string }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[], damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) {
const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies, damageRecords, round } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
const serverId = session.get('serverId');
let sid = session.get('sid');
let ip = session.get('ip');
let warInfo = gameData.war.get(battleId);
if (!warInfo) {
return resResult(STATUS.BATTLE_MISS_INFO);
}
const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode);
if (!BattleRecord || BattleRecord.status != 0) {
return resResult(STATUS.BATTLE_STATUS_WRONG);
}
let flag = 1; // 对比hero信息
let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord;
for (let { dataId } of heroes) {
if (dbSeqIds.indexOf(dataId) == -1) flag = 0;
}
if (!flag) {
return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR);
}
let role = await RoleModel.findByRoleId(roleId, 'lv');
let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess?-1 * warInfo.cost: 0, sid, ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END); // 扣除体力
if (!apJson) {
return resResult(STATUS.BATTLE_ACTION_POINT_LACK);
}
// 检查record
let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionRecord || !expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
// 更新我方剩余血量
await ExpeditionRecordModel.updateHeroStatus(expeditionCode, expeditionRecord.heroes, heroes);
// 更新敌人剩余状态及战斗状态
let battleStatus = isSuccess ? EXPEDITION_WAR_RECORD_STATUS.SUCCESS : EXPEDITION_WAR_RECORD_STATUS.FAIL;
expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, battleStatus, enemies);
// 更新battleRecord状态
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: { status: isSuccess ? 1 : 2, star, ...getBattleRecordParam(damageRecords, round) }
}, true);
// 更新点数
role = await RoleModel.increaseExpeditionPoint(roleId, isSuccess ? dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS : 0);
let { expeditionPoint = 0, warStar = [] } = role;
// 关卡奖励
let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess);
let reward = await warReward.saveReward(1);
let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验
let curWarStar = warStar.find(cur => cur.id == battleId);
let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars);
if (isSuccess) {
// 更新下一关状态
await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
if(!curWarStar) { // 首通
reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes });
}
if (!curWarStar || newStar > curWarStar.star) {
await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars });
}
}
await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, star, isSuccess);
return resResult(STATUS.SUCCESS, {
expeditionCode, expeditionId,
battleCode, battleId,
battleStatus: expeditionWarRecord.battleStatus,
battleGoods: reward,
expeditionPoint,
createdAt: getSeconds(createdAt),
...actordata
});
}
/**
* 领取点数宝箱
* 领取点数宝箱,不扣除点数,那么就需要记录领取状态并且有返回
*/
async pointReward(msg: { point: number }, session: BackendSession) {
const { point } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
const serverId = session.get('serverId');
let role = await RoleModel.findByRoleId(roleId);
let { expeditionPoint } = role;
let dicExpeditionPoint = gameData.expeditionPoint;
let curDicExpeditionPoint = dicExpeditionPoint.get(point);
if (!curDicExpeditionPoint) {
return resResult(STATUS.EXPEDITION_MISS_POINT_INFO);
}
if (point > expeditionPoint) {
return resResult(STATUS.EXPEDITION_POINT_NOT_ENOUGH);
}
let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId);
if (pointStatusInDatabase) {
let { rewards } = pointStatusInDatabase;
let curReward = rewards.find(cur => cur.point == point);
if (curReward && curReward.received) {
return resResult(STATUS.EXPEDITION_WRONG_RECEIVE_STATUS);
}
}
// 标记状态
let { rewards: resultRewards } = await ExpeditionPointModel.updatePointStatus(roleId, point, curDicExpeditionPoint.reward);
let hasReceivedAll = true, maxPoint = 0;
for (let [point] of dicExpeditionPoint) {
let curReward = resultRewards.find(cur => cur.point == point);
if (!curReward || !curReward.received) {
hasReceivedAll = false;
}
if (point > maxPoint) maxPoint = point;
}
if (hasReceivedAll) { // 全部领取了,刷新
await ExpeditionPointModel.completeStatus(roleId);
await RoleModel.increaseExpeditionPoint(roleId, maxPoint * -1);
}
let pointRewards = await getPointRewardStatus(roleId);
// 任务
await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EXPEDITION_BOX, { point });
let goods = await addItems(roleId, roleName, sid, curDicExpeditionPoint.reward, ITEM_CHANGE_REASON.EXPEDITION_POINT_REWARD);
return resResult(STATUS.SUCCESS, {
costPoint: hasReceivedAll ? maxPoint : 0,
pointRewards,
goods
})
}
async debugResetResetNum(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await RoleModel.updateRoleInfo(roleId, { expeditionResetCnt: 0 });
return resResult(STATUS.SUCCESS);
}
}
import { Application, BackendSession, HandlerService, } from 'pinus';
import { BattleRecordModel } from '@db/BattleRecord';
import { ExpeditionRecordModel } from '@db/ExpeditionRecord';
import { ExpeditionWarRecordModel } from '@db/ExpeditionWarRecord';
import { ExpeditionPointModel } from '@db/ExpeditionPoint';
import { RoleModel } from '@db/Role';
import { genCode, getWarTypeName } from '@pubUtils/util';
import { getPointRewardStatus, getResetRemainCnt, findOrCreateEnemies, getExpeditionStatus } from '../../../services/expeditionService';
import { DEBUG_MAGIC_WORD, EXPEDITION_WAR_RECORD_STATUS, ITEM_CHANGE_REASON, KING_EXP_RATIO_TYPE, TASK_TYPE, TA_EVENT } from '../../../consts';
import { WarReward } from '../../../services/warRewardService';
import { addItems } from '../../../services/role/rewardService';
import { getAp, setAp } from '../../../services/actionPointService';
import { STATUS } from '@consts/statusCode';
import { resResult } from '@pubUtils/util';
import { calculateWarStar, checkBattleHeroes, getBattleRecordParam, roleLevelup } from '../../../services/normalBattleService';
import { checkTask, checkTaskInBattleEnd, checkTaskInBattleStart, checkTaskInSkipExpedition } from '../../../services/task/taskService';
import { gameData } from '@pubUtils/data';
import * as dicParam from '@pubUtils/dicParam';
import { getSeconds, nowSeconds } from '@pubUtils/timeUtil';
import { reportTAEvent } from '../../../services/sdkService';
import { getSumCe } from '../../../services/playerCeService';
import { vipCanSkipExpedition } from '../../../services/activity/monthlyTicketService';
import { isHeroHidden } from '../../../services/dataService';
import { pvpEndParamInter } from '@pubUtils/interface';
export default function (app: Application) {
new HandlerService(app, {});
return new ExpeditionBattleHandler(app);
}
export class ExpeditionBattleHandler {
constructor(private app: Application) {
}
/**
* 获取初始数据
* 获取当前远征挑战情况,远征点数,点数宝箱领取情况 */
async getStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let res = await getExpeditionStatus(roleId, roleName);
if (!res) return resResult(STATUS.ROLE_IS_NOT_INIT);
return resResult(STATUS.SUCCESS, res);
}
/**
* 重置远征本
* 每天5点可以重置远征本 */
async resetStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let curTime = new Date();
let { needRefresh, resetCnt } = await getResetRemainCnt(curTime, roleId);
if (resetCnt <= 0) {
return resResult(STATUS.EXPEDITION_RESET_NUM_NOT_ENOUGH)
}
await ExpeditionRecordModel.hideRecord(roleId); // 刷掉旧关卡
// 我方战力
let myCe = await getSumCe(roleId);
// 每一关的挑战状态
let { expeditionCode, heroes } = await ExpeditionRecordModel.createRecord({
roleId, roleName, heroes: [], myCe
});
await findOrCreateEnemies(roleId, myCe, expeditionCode, 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
await RoleModel.increaseExpeditionResetCnt(roleId, needRefresh, curTime);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCode(expeditionCode);
let curLv = 0;
if (expeditionWarRecord.length > 0) {
curLv = expeditionWarRecord[expeditionWarRecord.length - 1].expeditionId;
}
return resResult(STATUS.SUCCESS, {
expeditionCode,
curLv,
expeditionWarRecord,
heroes,
resetCnt: resetCnt - 1
});
}
/**
* 获取敌军数据
* 匹配其他玩家,或机器人数据
*/
async getEnemies(msg: { expeditionCode: string, expeditionId: number }, session: BackendSession) {
const roleId = session.get('roleId');
// const roleName = session.get('roleName');
const { expeditionCode, expeditionId } = msg;
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (expeditionWarRecord && (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS)) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
let { myCe } = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let curExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING);
if (!curExpeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MATCH_NO_PLAYER);
}
let { battleId, mapseid, enemyFrom, enemies, battleStatus, ce: curCe } = curExpeditionWarRecord;
let nextCe = 0; // 下一关战力
if (gameData.expedition.has(expeditionId + 1)) {
let nextExpeditionWarRecord = await findOrCreateEnemies(roleId, myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.HIDE);
if (nextExpeditionWarRecord) nextCe = nextExpeditionWarRecord.ce;
}
return resResult(STATUS.SUCCESS, {
expeditionCode, expeditionId, battleId, mapseid,
battleStatus,
enemyFrom,
enemies,
curCe,
nextCe
});
}
/**
* 进入战斗
* 记录我军数据,生成战斗唯一表示,记录状态
*/
async checkBattle(msg: { expeditionCode: string, expeditionId: number, battleId: number, heroes: number[] }, session: BackendSession) {
const { expeditionCode, expeditionId, battleId, heroes: seqIds = [] } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let ip = session.get('ip');
let serverId = session.get('serverId');
let sid = session.get('sid');
let warInfo = gameData.war.get(battleId);
if (!warInfo) {
return resResult(STATUS.BATTLE_MISS_INFO);
}
let role = await RoleModel.findByRoleId(roleId, 'lv warStar');
let apJson = await getAp(roleId, ip, role.lv);
let { ap } = apJson;
if (ap < warInfo.cost) {
return resResult(STATUS.BATTLE_ACTION_POINT_LACK);
}
// 前置关卡是否挑战过
let previousGk = warInfo.previousGk;
if (previousGk) {
let preBattle = role.warStar.findIndex(cur => cur.id == previousGk);
if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK);
}
let { isOK, hids } = await checkBattleHeroes(roleId, seqIds);
if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
if (expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
const battleCode = genCode(8);
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: {
roleId, roleName, battleId,
status: 0,
warName: warInfo.gk_name,
warType: warInfo.warType,
record: { heroes: hids, seqIds }
}
}, true);
let result = await ExpeditionWarRecordModel.updateBattleCode(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.WAITING, battleCode);
await checkTaskInBattleStart(serverId, roleId, sid, battleId);
return resResult(STATUS.SUCCESS, {
expeditionCode,
expeditionId,
battleId,
battleCode,
battleStatus: result.battleStatus
});
}
/**
* 跳过
*/
async skipExpedition(msg: { expeditionCode: string, expeditionId: number, battleId: number }, session: BackendSession) {
const { expeditionCode, expeditionId, battleId } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let dicExpedition = gameData.expedition.get(expeditionId);
if(dicExpedition.warId != battleId) return resResult(STATUS.WRONG_PARMS);
let dicWar = gameData.war.get(battleId);
if(!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND);
// 前置关卡是否挑战过
let role = await RoleModel.findByRoleId(roleId, 'warStar topLineupCe vipStartTime')
let { warStar, topLineupCe, vipStartTime } = role;
let previousGk = dicWar.previousGk;
if (previousGk) {
let preBattle = warStar.findIndex(cur => cur.id == previousGk);
if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK);
}
// 检查record
let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionRecord || !expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
if(expeditionWarRecord.battleStatus == EXPEDITION_WAR_RECORD_STATUS.SUCCESS) {
return resResult(STATUS.EXPEDITION_DUPLICATE_CHALLENGE);
}
// 检查战力是否足够
if(!vipCanSkipExpedition(expeditionWarRecord.ce, topLineupCe, vipStartTime)) {
return resResult(STATUS.EXPEDITION_SKIP_POWER_NOT_ENOUGH)
}
// 更新敌人剩余状态及战斗状态
expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, EXPEDITION_WAR_RECORD_STATUS.SUCCESS, []);
// 更新点数
role = await RoleModel.increaseExpeditionPoint(roleId, dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS);
// 关卡奖励
let warReward = new WarReward(roleId, roleName, sid, battleId, true);
let reward = await warReward.saveReward(1);
let curWarStar = warStar.find(cur => cur.id == battleId);
let { newWarStars, newStar } = calculateWarStar(warStar, battleId, []);
if (!curWarStar || newStar > curWarStar.star) {
role = await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars });
}
// 更新下一关状态
if (gameData.expedition.has(expeditionId + 1)) {
await findOrCreateEnemies(roleId, expeditionRecord.myCe, expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
}
await checkTaskInSkipExpedition(serverId, roleId, sid, battleId);
return resResult(STATUS.SUCCESS, {
expeditionCode,
expeditionId,
battleId,
goods: reward,
expeditionPoint: role.expeditionPoint
});
}
/**
* 战斗结算
* 结算战斗奖励,更新远征状态
*/
async battleEnd(msg: { expeditionCode: string, expeditionId: number, battleCode: string, battleId: number, isSuccess: boolean, heroes: Array<{ dataId: number, hp: number, ap: number, shield: number, others: string }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[], damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) {
const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies, damageRecords, round } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
const serverId = session.get('serverId');
let sid = session.get('sid');
let ip = session.get('ip');
let warInfo = gameData.war.get(battleId);
if (!warInfo) {
return resResult(STATUS.BATTLE_MISS_INFO);
}
const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode);
if (!BattleRecord || BattleRecord.status != 0) {
return resResult(STATUS.BATTLE_STATUS_WRONG);
}
let flag = 1; // 对比hero信息
let { record: { heroes: dbHeroes, seqIds: dbSeqIds }, createdAt } = BattleRecord;
for (let { dataId } of heroes) {
if (dbSeqIds.indexOf(dataId) == -1) flag = 0;
}
if (!flag) {
return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR);
}
let role = await RoleModel.findByRoleId(roleId, 'lv');
let apJson = await setAp(serverId, roleId, ip, role.lv, isSuccess?-1 * warInfo.cost: 0, sid, ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END); // 扣除体力
if (!apJson) {
return resResult(STATUS.BATTLE_ACTION_POINT_LACK);
}
// 检查record
let expeditionRecord = await ExpeditionRecordModel.getExpeditionRecordByCode(expeditionCode);
let expeditionWarRecord = await ExpeditionWarRecordModel.getRecordByCodeAndId(expeditionCode, expeditionId);
if (!expeditionRecord || !expeditionWarRecord) {
return resResult(STATUS.EXPEDITION_MISS_WAR_RECORD);
}
// 更新我方剩余血量
await ExpeditionRecordModel.updateHeroStatus(expeditionCode, expeditionRecord.heroes, heroes);
// 更新敌人剩余状态及战斗状态
let battleStatus = isSuccess ? EXPEDITION_WAR_RECORD_STATUS.SUCCESS : EXPEDITION_WAR_RECORD_STATUS.FAIL;
expeditionWarRecord = await ExpeditionWarRecordModel.updateEnemiesStatus(expeditionCode, expeditionId, battleStatus, enemies);
// 更新battleRecord状态
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: { status: isSuccess ? 1 : 2, star, ...getBattleRecordParam(damageRecords, round) }
}, true);
// 更新点数
role = await RoleModel.increaseExpeditionPoint(roleId, isSuccess ? dicParam.EXPEDITION_CONST.EXPEDITION_CONST_POINTS : 0);
let { expeditionPoint = 0, warStar = [] } = role;
// 关卡奖励
let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess);
let reward = await warReward.saveReward(1);
let actordata = await roleLevelup(KING_EXP_RATIO_TYPE.BATTLE, roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验
let curWarStar = warStar.find(cur => cur.id == battleId);
let { newWarStars, newStar } = calculateWarStar(warStar, battleId, stars);
if (isSuccess) {
// 更新下一关状态
await ExpeditionWarRecordModel.updateStatus(expeditionCode, expeditionId + 1, EXPEDITION_WAR_RECORD_STATUS.WAITING);
if(!curWarStar) { // 首通
reportTAEvent(roleId, TA_EVENT.GK_FIRST_PASS, { war_id: battleId, war_type: getWarTypeName(warInfo.warType), pass_time: Date.now(), pass_duration: nowSeconds() - getSeconds(createdAt), hero_list: dbHeroes });
}
if (!curWarStar || newStar > curWarStar.star) {
await RoleModel.updateRoleInfo(roleId, { warStar: newWarStars });
}
}
await checkTaskInBattleEnd(serverId, roleId, sid, battleId, dbHeroes, star, isSuccess);
return resResult(STATUS.SUCCESS, {
expeditionCode, expeditionId,
battleCode, battleId,
battleStatus: expeditionWarRecord.battleStatus,
battleGoods: reward,
expeditionPoint,
createdAt: getSeconds(createdAt),
...actordata
});
}
/**
* 领取点数宝箱
* 领取点数宝箱,不扣除点数,那么就需要记录领取状态并且有返回
*/
async pointReward(msg: { point: number }, session: BackendSession) {
const { point } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
const serverId = session.get('serverId');
let role = await RoleModel.findByRoleId(roleId);
let { expeditionPoint } = role;
let dicExpeditionPoint = gameData.expeditionPoint;
let curDicExpeditionPoint = dicExpeditionPoint.get(point);
if (!curDicExpeditionPoint) {
return resResult(STATUS.EXPEDITION_MISS_POINT_INFO);
}
if (point > expeditionPoint) {
return resResult(STATUS.EXPEDITION_POINT_NOT_ENOUGH);
}
let pointStatusInDatabase = await ExpeditionPointModel.getExpeditionPoint(roleId);
if (pointStatusInDatabase) {
let { rewards } = pointStatusInDatabase;
let curReward = rewards.find(cur => cur.point == point);
if (curReward && curReward.received) {
return resResult(STATUS.EXPEDITION_WRONG_RECEIVE_STATUS);
}
}
// 标记状态
let { rewards: resultRewards } = await ExpeditionPointModel.updatePointStatus(roleId, point, curDicExpeditionPoint.reward);
let hasReceivedAll = true, maxPoint = 0;
for (let [point] of dicExpeditionPoint) {
let curReward = resultRewards.find(cur => cur.point == point);
if (!curReward || !curReward.received) {
hasReceivedAll = false;
}
if (point > maxPoint) maxPoint = point;
}
if (hasReceivedAll) { // 全部领取了,刷新
await ExpeditionPointModel.completeStatus(roleId);
await RoleModel.increaseExpeditionPoint(roleId, maxPoint * -1);
}
let pointRewards = await getPointRewardStatus(roleId);
// 任务
await checkTask(serverId, roleId, sid, TASK_TYPE.BATTLE_EXPEDITION_BOX, { point });
let goods = await addItems(roleId, roleName, sid, curDicExpeditionPoint.reward, ITEM_CHANGE_REASON.EXPEDITION_POINT_REWARD);
return resResult(STATUS.SUCCESS, {
costPoint: hasReceivedAll ? maxPoint : 0,
pointRewards,
goods
})
}
async debugResetResetNum(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
await RoleModel.updateRoleInfo(roleId, { expeditionResetCnt: 0 });
return resResult(STATUS.SUCCESS);
}
}
@@ -1,61 +1,62 @@
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { LadderMatchModel } from '../../../db/LadderMatch';
import { HeroModel, HeroType } from '../../../db/Hero';
import { ArtifactModel } from '../../../db/Artifact';
import { getHeroesAttributes } from '../../../services/playerCeService';
import { gameData } from '../../../pubUtils/data';
import { LadderOppDetailHeroReturn } from '../../../domain/battleField/ladder';
import { resResult } from '../../../pubUtils/util';
import { STATUS } from '../../../consts/statusCode';
import { RoleType } from '../../../db/Role';
import { FRIEND_BATTLE_DISPATCH_JSONID } from '../../../consts';
import { getLadderDefCe } from '../../../services/redisService';
export default function (app: Application) {
new HandlerService(app, {});
return new FriendBattleHandler(app);
}
export class FriendBattleHandler {
constructor(private app: Application) {
}
async getFriendOpp(msg: { roleId: string }, session: BackendSession) {
const { roleId: targetRoleId, } = msg;
let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(targetRoleId);
if (!hisLadderData || !hisLadderData.defense || !hisLadderData.defense.heroes) return resResult(STATUS.LADDER_NOT_OPEN);
let artifactSeids = [], subHids: number[] = [];
for (let { hero, subHid } of hisLadderData.defense.heroes) {
let dbHero = <HeroType>hero;
if (dbHero) artifactSeids.push(dbHero.artifact);
if (subHid) subHids.push(subHid);
}
let artifacts = await ArtifactModel.findbySeqIds(targetRoleId, artifactSeids);
let subHeroes = await HeroModel.findByHidRange(subHids, targetRoleId, 'hid skinId');
let attrByHid = await getHeroesAttributes(targetRoleId);
let dicWarJson = gameData.warJson.get(FRIEND_BATTLE_DISPATCH_JSONID);
let result: LadderOppDetailHeroReturn[] = [];
for (let obj of hisLadderData.defense.heroes) {
const { dataId, subHid, actorId } = obj;
let warJson = dicWarJson.find(cur => cur.dataId == dataId);
if (warJson) {
let subHero = subHeroes.find(sub => sub.hid == subHid);
let rec = new LadderOppDetailHeroReturn(warJson, obj, artifacts, subHero);
let attr = attrByHid.get(actorId);
if (attr) {
rec.setAttribute(attr.getAttributesToString());
}
result.push(rec);
}
}
const role = <RoleType>hisLadderData.role;
const title = role?.title || 1;
const combo = hisLadderData.defense.combo || [];
const defCe = await getLadderDefCe(targetRoleId);
return resResult(STATUS.SUCCESS, { title, combo, defCe, heroes: result })
}
}
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { LadderMatchModel } from '@db/LadderMatch';
import { HeroModel, HeroType } from '@db/Hero';
import { ArtifactModel } from '@db/Artifact';
import { getHeroesAttributes } from '../../../services/playerCeService';
import { gameData } from '@pubUtils/data';
import { LadderOppDetailHeroReturn } from '@domain/battleField/ladder';
import { resResult } from '@pubUtils/util';
import { STATUS } from '@consts/statusCode';
import { RoleType } from '@db/Role';
import { FRIEND_BATTLE_DISPATCH_JSONID } from '../../../consts';
import { getLadderDefCe } from '../../../services/redisService';
export default function (app: Application) {
new HandlerService(app, {});
return new FriendBattleHandler(app);
}
export class FriendBattleHandler {
constructor(private app: Application) {
}
async getFriendOpp(msg: { roleId: string }, session: BackendSession) {
const { roleId: targetRoleId, } = msg;
let hisLadderData = await LadderMatchModel.findByRoleIdAndInclude(targetRoleId);
if (!hisLadderData || !hisLadderData.defense || !hisLadderData.defense.heroes) return resResult(STATUS.LADDER_NOT_OPEN);
let artifactSeids = [], subHids: number[] = [];
for (let { hero, subHid } of hisLadderData.defense.heroes) {
let dbHero = <HeroType>hero;
if (dbHero) artifactSeids.push(dbHero.artifact);
if (subHid) subHids.push(subHid);
}
let artifacts = await ArtifactModel.findbySeqIds(targetRoleId, artifactSeids);
let subHeroes = await HeroModel.findByHidRange(subHids, targetRoleId, 'hid skinId');
let attrByHid = await getHeroesAttributes(targetRoleId);
let dicWarJson = gameData.warJson.get(FRIEND_BATTLE_DISPATCH_JSONID);
let result: LadderOppDetailHeroReturn[] = [];
for (let obj of hisLadderData.defense.heroes) {
const { dataId, subHid, actorId } = obj;
let warJson = dicWarJson.find(cur => cur.dataId == dataId);
if (warJson) {
let subHero = subHeroes.find(sub => sub.hid == subHid);
let rec = new LadderOppDetailHeroReturn(warJson, obj, artifacts, subHero);
let attr = attrByHid.get(actorId);
if (attr) {
rec.setAttribute(attr.getAttributesToString());
}
result.push(rec);
}
}
const role = <RoleType>hisLadderData.role;
const title = role?.title || 1;
const combo = hisLadderData.defense.combo || [];
const defCe = await getLadderDefCe(targetRoleId);
return resResult(STATUS.SUCCESS, { title, combo, defCe, heroes: result })
}
}
@@ -1,455 +1,456 @@
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { isArray, pick } from 'underscore';
import { gameData } from '../../../pubUtils/data';
import { STATUS } from '../../../consts/statusCode';
import { arrToMap, resResult } from '../../../pubUtils/util';
import { getTimeFunM } from '../../../pubUtils/timeUtil';
import { LadderMatchModel, LadderUpdateInter } from '../../../db/LadderMatch';
import { battleEndWhenChange, checkRank, generateInitRecInfo, generateOppPlayers, getBuyCntCost, getLadderData, getLadderEnemies, getLadderOppDetailData, getLadderOppStatus, getNumberArr, ladderBattleEndReward, pushLadderIconShow, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward, uniqueArr } from '../../../services/ladderService';
import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '../../../domain/battleField/ladder';
import { LadderMatchRecModel } from '../../../db/LadderMatchRec';
import { HeroModel } from '../../../db/Hero';
import { LADDER } from '../../../pubUtils/dicParam';
import { handleCost } from '../../../services/role/rewardService';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY, WAR_TYPE } from '../../../consts';
import { checkBattleHeroesByHid, getBattleRecordParam } from '../../../services/normalBattleService';
import { ServerlistModel } from '../../../db/Serverlist';
import { saveLadderDefCeByData } from '../../../services/redisService';
import { pushLadderTopChangeMsg } from '../../../services/sysChatService';
import { checkTaskInLadderEnd, checkTaskInLadderStart, checkTaskInLadderSweep } from '../../../services/task/taskService';
import { BattleRecordModel } from '../../../db/BattleRecord';
import { isHeroHidden } from '../../../services/dataService';
import { getRemoteRplFilePath, getRemoteRplPrefix } from '../../../pubUtils/battleUtils';
import { pvpEndParamInter } from '../../../pubUtils/interface';
import { Combo } from '../../../domain/battleField/pvp';
export default function (app: Application) {
new HandlerService(app, {});
return new LadderHandler(app);
}
export class LadderHandler {
constructor(private app: Application) {
}
// 1. 获取主界面
async getData(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let result = await getLadderData(roleId, true)
return resResult(STATUS.SUCCESS, result);
}
// 2. 获取对手阵容信息
async getOppLineup(msg: { roleId: string, rank: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let { roleId: targetRoleId, rank } = msg;
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let isRobot = targetRoleId.startsWith('robot');
let result = new LadderOppLineupReturn();
result.setMyRank(ladderData.rank);
if(isRobot) {
let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank);
let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
result.setRobot(dicLadderDifficultRatio, dicWarJson);
} else {
let hisLadderData = await LadderMatchModel.findOne({ roleId: targetRoleId })
.populate('role', 'roleId roleName head frame spine heads frames spines title lv guildName updatedAt')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid subActorId')
.lean();
result.setPlayer(hisLadderData);
}
return resResult(STATUS.SUCCESS, result);
}
// 3. 点击挑战
async chooseOpp(msg: { roleId: string, rank: number, myRank: number }, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let sid = session.get('sid');
let { roleId: targetRoleId, rank, myRank } = msg;
// 检查双方排名等,不行的刷新对手回去
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
if(!checkRank(myRank, rank)) return resResult(STATUS.LADDER_RANK_ERROR);
let { status, isRobot, hisLadderData } = await getLadderOppStatus(ladderData, targetRoleId, myRank, rank);
if(status != LADDER_OPP_STATUS.BATTLE) {
// await LadderMatchModel.unlock(serverId, targetRoleId);
let oppPlayers = await refreshLadderEnemies(ladderData);
return resResult(STATUS.SUCCESS, {
status, oppPlayers
});
}
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
let update: LadderUpdateInter = {};
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.challengeCnt + 1 > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) {
await LadderMatchModel.unlock(serverId, targetRoleId);
return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX);
}
update.challengeCnt = refOppObj.challengeCnt + 1;
ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update);
// 创建ladderMatchRec,发行battleCode
let attackInfo = await generateInitRecInfo(false, false, ladderData.rank, ladderData);
let defenseInfo = await generateInitRecInfo(isRobot, true, rank, hisLadderData);
let rec = await LadderMatchRecModel.createRec(serverId, roleId, targetRoleId, hisLadderData?.defense, attackInfo, defenseInfo);
// 倒计时,倒计时结束没有check设为失败并发失败通知
pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.checkTime, LADDER_STATUS.CHECK);
let result = await getLadderOppDetailData(rec);
await checkTaskInLadderStart(serverId, roleId, sid);
return resResult(STATUS.SUCCESS, {
status,
challengeCnt: ladderData.challengeCnt,
...result
});
}
// 4. 出战撤退
async giveupCheck(msg: { battleCode: string }, session: BackendSession) {
let roleId = session.get('roleId');
let { battleCode } = msg;
// 更新ladderMatchRec
let rec = await LadderMatchRecModel.giveup(roleId, battleCode);
if(rec) {
pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(rec.battleCode);
if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId);
}
return resResult(STATUS.SUCCESS, { status: 0, time: 0 });
}
// 5. 获取对手具体战场数据
async getOppData(msg: { battleCode: string }, session: BackendSession) {
let roleId = session.get('roleId');
let { battleCode } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status == LADDER_STATUS.COMPLETE || rec.status == LADDER_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE);
let result = await getLadderOppDetailData(rec);
return resResult(STATUS.SUCCESS, result);
}
// 6. 布完阵开始挑战
async checkBattle(msg: { battleCode: string, battleId: number, heroes: { actorId: number, order: number }[] }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleId');
let { battleId, battleCode, heroes } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status != LADDER_STATUS.CHECK) return resResult(STATUS.LADDER_REC_STATUS_ERR);
for(let { actorId } of heroes) {
if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN);
}
let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId));
if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
let attackHeroes = dbHeroes.map(hero => {
let heroInfo = new LadderOppPlayerHeroInfo();
heroInfo.setByDefenseHero(hero);
return heroInfo;
});
let warInfo = gameData.war.get(battleId);
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: {
roleId, roleName, battleId,
status: 0,
warName: warInfo?.gk_name,
warType: warInfo?.warType,
}
});
rec = await LadderMatchRecModel.startBattle(battleCode, attackHeroes);
pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.battleTime, LADDER_STATUS.BATTLE);
return resResult(STATUS.SUCCESS, {
time: Math.floor(rec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN,
battleCode: rec.battleCode
})
}
// 7. 挑战结算
async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let { battleCode, isSuccess, damageRecords, round } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status != LADDER_STATUS.BATTLE) return resResult(STATUS.LADDER_REC_STATUS_ERR);
let rank = rec.defenseInfo.oldRank;
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
// 取消 checkBattle 的倒计时
pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(battleCode);
let result = new LadderDataReturn();
// 交换双方排名, transaction
let { isChange, atkLadderMatch, defLadderMatch, endTime } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo);
if(isChange) {
let oppPlayers = await battleEndWhenChange(atkLadderMatch, defLadderMatch, true);
result.setOppPlayers(oppPlayers);
rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank);
if(atkLadderMatch.rank == 1) {
pushLadderTopChangeMsg(roleId, roleName, serverId);
}
} else {
rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime);
let oppPlayers = await getLadderEnemies(atkLadderMatch);
result.setOppPlayers(oppPlayers);
}
await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } });
if(defLadderMatch) {
await LadderMatchModel.unlock(defLadderMatch.serverId, defLadderMatch.roleId);
}
let historyRank = ladderData.historyRank;
ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: (historyRank > atkLadderMatch.rank || historyRank == 0)? atkLadderMatch.rank: historyRank });
result.setLadderData(ladderData, rec);
// 获取奖励
let rewardResult = await ladderBattleEndReward(roleId, roleName, sid, ladderData.historyRank, isSuccess, historyRank, 1);
let { battleGoods = [], breakGoods = [] } = rewardResult||{};
await checkTaskInLadderEnd(serverId, roleId, sid, isSuccess, historyRank, atkLadderMatch.rank);
if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushLadderIconShow(rec.roleId2, true);
return resResult(STATUS.SUCCESS, {...pick(result, ['rank', 'historyRank', 'challengeCnt','status', 'time', 'oppPlayers']), battleGoods, breakGoods});
}
// 8. 战5次(扫荡)
async battleSweep(msg: { roleId: string, rank: number, count: number }, session: BackendSession) {
let serverId = session.get('serverId');
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { roleId: targetRoleId, rank, count } = msg;
if(count > LADDER.LADDER_INITIAL_CHALLENGE_TIMES) {
return resResult(STATUS.LADDER_SWEEP_TIMES_OVER);
}
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
if(ladderData.rank >= rank) return resResult(STATUS.LADDER_RANK_ERR);
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
let update: LadderUpdateInter = {};
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.challengeCnt + count > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) {
return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX);
}
update.challengeCnt = refOppObj.challengeCnt + count;
ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update);
// 获取奖励
let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, rank, count);
await checkTaskInLadderSweep(serverId, roleId, sid, count)
return resResult(STATUS.SUCCESS, {
challengeCnt: ladderData.challengeCnt,
battleGoods
});
}
// 9. 设置防守阵容
async saveDefense(msg: { warId: number, heroes: { actorId: number, ai: number, dataId: number, order: number, subHid?: number }[], combo: Combo[] }, session: BackendSession) {
let { warId, heroes, combo } = msg;
let roleId = session.get('roleId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let hids: number[] = heroes.map(cur => cur.actorId);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
for(let { actorId, subHid } of heroes) {
let dicHero = gameData.hero.get(actorId);
if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB);
if(subHid && hids.indexOf(subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE);
}
let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true);
let defenseHeroes = heroes.map(cur => {
let dbHero = dbHeroes.find(ccur => ccur.hid == cur.actorId);
return dbHero && new LadderDefenseHero(cur, dbHero._id, dbHero.ce);
}).filter(cur => cur);
let defense = new LadderDefense(defenseHeroes, warId, combo);
ladderData = await LadderMatchModel.updateByRoleId(roleId, { defense, hasDefense: true });
// 返回
let result = new LadderDataReturn();
result.setLadderData(ladderData);
await saveLadderDefCeByData(roleId, ladderData);
return resResult(STATUS.SUCCESS, pick(result, 'defense'));
}
// 10. 刷新对手
async refreshOppPlayers(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let sid = session.get('sid');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let update: LadderUpdateInter = {};
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.refOppCnt + 1 > LADDER.LADDER_REFRESH_TIMES) {
return resResult(STATUS.LADDER_REFRESH_CNT_MAX);
}
update.refOppCnt = refOppObj.refOppCnt + 1;
let oppPlayers = await refreshLadderEnemies(ladderData, update);
// 返回
return resResult(STATUS.SUCCESS, { refOppCnt: update.refOppCnt, oppPlayers });
}
// 11. 购买次数
async buyCnt(msg: { count: number }, session: BackendSession) {
let { count } = msg;
let roleId = session.get('roleId');
let sid = session.get('sid');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let update: LadderUpdateInter = {};
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.buyCnt + count > LADDER.LADDER_CHALLENGE_COST_TIMES) {
return resResult(STATUS.LADDER_BUY_MAX);
}
let consumes = getBuyCntCost(refOppObj.buyCnt, count);
if(!consumes) return resResult(STATUS.LADDER_BUY_MAX);
let consumeResult = await handleCost(roleId, sid, consumes||[], ITEM_CHANGE_REASON.LADDER_BUY_CNT);
if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
update.buyCnt = refOppObj.buyCnt + count;
ladderData = await LadderMatchModel.updateByRoleId(roleId, update);
// 返回
let result = new LadderDataReturn();
result.setLadderData(ladderData);
return resResult(STATUS.SUCCESS, pick(result, ['buyCnt', 'challengeCnt']));
}
// 12. 获取战报信息(2天内)
async getRec(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let list = await LadderMatchRecModel.findRecentRec(roleId, <number>getTimeFunM().getBeforeDay(2));
return resResult(STATUS.SUCCESS, {
list: list.map(rec => {
const { roleId1, battleCode, hasRpl, remoteUrl } = rec;
const rplFileUrl = battleCode && hasRpl ? remoteUrl : '';
return { ...rec, rplFileUrl };
}),
rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env'))
});
}
// debug接口
// 重置挑战次数 & 购买次数
async resetCnt(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) });
return resResult(STATUS.SUCCESS);
}
async setMyRank(msg: { magicWord: string, rank: number }, session: BackendSession) {
const { magicWord, rank } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let atkLadderMatch = await LadderMatchModel.findByRoleId(roleId);
if(!atkLadderMatch || !atkLadderMatch.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let myRank = atkLadderMatch.rank;
let defLadderMatch = await LadderMatchModel.findByRank(serverId, rank);
if(defLadderMatch) {
atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: myRank, historyRank: rank } }, { new: true }).lean();
defLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defLadderMatch.roleId }, { $set: { rank: myRank, oldRank: rank } }, { new: true }).lean();
} else {
atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: atkLadderMatch.rank, historyRank: rank } }, { new: true }).lean();
}
await battleEndWhenChange(atkLadderMatch, defLadderMatch, true);
return resResult(STATUS.SUCCESS);
}
async setMyOpp(msg: { magicWord: string, oppRanks: number[] }, session: BackendSession) {
const { magicWord, oppRanks } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.WRONG_PARMS);
}
if(!isArray(oppRanks) || oppRanks.length <= 0) return resResult(STATUS.WRONG_PARMS);
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let topTen = getNumberArr(1, 10);
let ranks = [...topTen, ...oppRanks];
let newRanks = uniqueArr(ranks.sort((a, b) => a - b));
await generateOppPlayers(newRanks, serverId, roleId);
return resResult(STATUS.SUCCESS);
}
async sendDailyReward(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let servers = await ServerlistModel.findByEnv(pinus.app.get('env'));
for(let { id } of servers) {
await sendLadderDailyReward(id);
}
return resResult(STATUS.SUCCESS)
}
}
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
import { isArray, pick } from 'underscore';
import { gameData } from '@pubUtils/data';
import { STATUS } from '@consts/statusCode';
import { arrToMap, resResult } from '@pubUtils/util';
import { getTimeFunM } from '@pubUtils/timeUtil';
import { LadderMatchModel, LadderUpdateInter } from '@db/LadderMatch';
import { battleEndWhenChange, checkRank, generateInitRecInfo, generateOppPlayers, getBuyCntCost, getLadderData, getLadderEnemies, getLadderOppDetailData, getLadderOppStatus, getNumberArr, ladderBattleEndReward, pushLadderIconShow, refreshLadderDaily, refreshLadderEnemies, sendLadderDailyReward, uniqueArr } from '../../../services/ladderService';
import { LadderDataReturn, LadderDefense, LadderDefenseHero, LadderOppDetailReturn, LadderOppLineupReturn, LadderOppPlayerHeroInfo, LadderOppPlayerReturn } from '@domain/battleField/ladder';
import { LadderMatchRecModel } from '@db/LadderMatchRec';
import { HeroModel } from '@db/Hero';
import { LADDER } from '@pubUtils/dicParam';
import { handleCost } from '../../../services/role/rewardService';
import { DEBUG_MAGIC_WORD, ITEM_CHANGE_REASON, LADDER_OPP_STATUS, LADDER_STATUS, REDIS_KEY, WAR_TYPE } from '../../../consts';
import { checkBattleHeroesByHid, getBattleRecordParam } from '../../../services/normalBattleService';
import { ServerlistModel } from '@db/Serverlist';
import { saveLadderDefCeByData } from '../../../services/redisService';
import { pushLadderTopChangeMsg } from '../../../services/sysChatService';
import { checkTaskInLadderEnd, checkTaskInLadderStart, checkTaskInLadderSweep } from '../../../services/task/taskService';
import { BattleRecordModel } from '@db/BattleRecord';
import { isHeroHidden } from '../../../services/dataService';
import { getRemoteRplFilePath, getRemoteRplPrefix } from '@pubUtils/battleUtils';
import { pvpEndParamInter } from '@pubUtils/interface';
import { Combo } from '@domain/battleField/pvp';
export default function (app: Application) {
new HandlerService(app, {});
return new LadderHandler(app);
}
export class LadderHandler {
constructor(private app: Application) {
}
// 1. 获取主界面
async getData(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let result = await getLadderData(roleId, true)
return resResult(STATUS.SUCCESS, result);
}
// 2. 获取对手阵容信息
async getOppLineup(msg: { roleId: string, rank: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let { roleId: targetRoleId, rank } = msg;
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let isRobot = targetRoleId.startsWith('robot');
let result = new LadderOppLineupReturn();
result.setMyRank(ladderData.rank);
if(isRobot) {
let dicLadderDifficultRatio = gameData.ladderDifficultRatio.get(rank);
let dicWar = gameData.war.get(dicLadderDifficultRatio.gkId);
let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
result.setRobot(dicLadderDifficultRatio, dicWarJson);
} else {
let hisLadderData = await LadderMatchModel.findOne({ roleId: targetRoleId })
.populate('role', 'roleId roleName head frame spine heads frames spines title lv guildName updatedAt')
.populate('defense.heroes.hero', 'hid skinId quality star colorStar lv skins job artifact subHid subActorId')
.lean();
result.setPlayer(hisLadderData);
}
return resResult(STATUS.SUCCESS, result);
}
// 3. 点击挑战
async chooseOpp(msg: { roleId: string, rank: number, myRank: number }, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let sid = session.get('sid');
let { roleId: targetRoleId, rank, myRank } = msg;
// 检查双方排名等,不行的刷新对手回去
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
if(!checkRank(myRank, rank)) return resResult(STATUS.LADDER_RANK_ERROR);
let { status, isRobot, hisLadderData } = await getLadderOppStatus(ladderData, targetRoleId, myRank, rank);
if(status != LADDER_OPP_STATUS.BATTLE) {
// await LadderMatchModel.unlock(serverId, targetRoleId);
let oppPlayers = await refreshLadderEnemies(ladderData);
return resResult(STATUS.SUCCESS, {
status, oppPlayers
});
}
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
let update: LadderUpdateInter = {};
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.challengeCnt + 1 > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) {
await LadderMatchModel.unlock(serverId, targetRoleId);
return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX);
}
update.challengeCnt = refOppObj.challengeCnt + 1;
ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update);
// 创建ladderMatchRec,发行battleCode
let attackInfo = await generateInitRecInfo(false, false, ladderData.rank, ladderData);
let defenseInfo = await generateInitRecInfo(isRobot, true, rank, hisLadderData);
let rec = await LadderMatchRecModel.createRec(serverId, roleId, targetRoleId, hisLadderData?.defense, attackInfo, defenseInfo);
// 倒计时,倒计时结束没有check设为失败并发失败通知
pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.checkTime, LADDER_STATUS.CHECK);
let result = await getLadderOppDetailData(rec);
await checkTaskInLadderStart(serverId, roleId, sid);
return resResult(STATUS.SUCCESS, {
status,
challengeCnt: ladderData.challengeCnt,
...result
});
}
// 4. 出战撤退
async giveupCheck(msg: { battleCode: string }, session: BackendSession) {
let roleId = session.get('roleId');
let { battleCode } = msg;
// 更新ladderMatchRec
let rec = await LadderMatchRecModel.giveup(roleId, battleCode);
if(rec) {
pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(rec.battleCode);
if(rec.defenseInfo && !rec.defenseInfo.isRobot) await LadderMatchModel.unlock(rec.serverId, rec.defenseInfo.roleId);
}
return resResult(STATUS.SUCCESS, { status: 0, time: 0 });
}
// 5. 获取对手具体战场数据
async getOppData(msg: { battleCode: string }, session: BackendSession) {
let roleId = session.get('roleId');
let { battleCode } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status == LADDER_STATUS.COMPLETE || rec.status == LADDER_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE);
let result = await getLadderOppDetailData(rec);
return resResult(STATUS.SUCCESS, result);
}
// 6. 布完阵开始挑战
async checkBattle(msg: { battleCode: string, battleId: number, heroes: { actorId: number, order: number }[] }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleId');
let { battleId, battleCode, heroes } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status != LADDER_STATUS.CHECK) return resResult(STATUS.LADDER_REC_STATUS_ERR);
for(let { actorId } of heroes) {
if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN);
}
let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId));
if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
let attackHeroes = dbHeroes.map(hero => {
let heroInfo = new LadderOppPlayerHeroInfo();
heroInfo.setByDefenseHero(hero);
return heroInfo;
});
let warInfo = gameData.war.get(battleId);
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
$set: {
roleId, roleName, battleId,
status: 0,
warName: warInfo?.gk_name,
warType: warInfo?.warType,
}
});
rec = await LadderMatchRecModel.startBattle(battleCode, attackHeroes);
pinus.app.rpc.systimer.systimerRemote.setLadderCountDown.broadcast(rec.battleCode, rec.battleTime, LADDER_STATUS.BATTLE);
return resResult(STATUS.SUCCESS, {
time: Math.floor(rec.battleTime/1000) + LADDER.LADDER_BATTLE_COUNTDOWN,
battleCode: rec.battleCode
})
}
// 7. 挑战结算
async battleEnd(msg: { battleCode: string, isSuccess: boolean, damageRecords: pvpEndParamInter[], round: number }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let { battleCode, isSuccess, damageRecords, round } = msg;
let rec = await LadderMatchRecModel.findByBattleCode(battleCode);
if(!rec || rec.roleId1 != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
if(rec.status != LADDER_STATUS.BATTLE) return resResult(STATUS.LADDER_REC_STATUS_ERR);
let rank = rec.defenseInfo.oldRank;
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
// 取消 checkBattle 的倒计时
pinus.app.rpc.systimer.systimerRemote.cancelLadderCountDown.broadcast(battleCode);
let result = new LadderDataReturn();
// 交换双方排名, transaction
let { isChange, atkLadderMatch, defLadderMatch, endTime } = await LadderMatchModel.changeRank(isSuccess, rec.attackInfo, rec.defenseInfo);
if(isChange) {
let oppPlayers = await battleEndWhenChange(atkLadderMatch, defLadderMatch, true);
result.setOppPlayers(oppPlayers);
rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime, atkLadderMatch.rank, defLadderMatch? defLadderMatch.rank: rec.attackInfo.oldRank);
if(atkLadderMatch.rank == 1) {
pushLadderTopChangeMsg(roleId, roleName, serverId);
}
} else {
rec = await LadderMatchRecModel.battleEnd(battleCode, isSuccess, endTime);
let oppPlayers = await getLadderEnemies(atkLadderMatch);
result.setOppPlayers(oppPlayers);
}
await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2, ...getBattleRecordParam(damageRecords, round) } });
if(defLadderMatch) {
await LadderMatchModel.unlock(defLadderMatch.serverId, defLadderMatch.roleId);
}
let historyRank = ladderData.historyRank;
ladderData = await LadderMatchModel.updateByRoleId(roleId, { historyRank: (historyRank > atkLadderMatch.rank || historyRank == 0)? atkLadderMatch.rank: historyRank });
result.setLadderData(ladderData, rec);
// 获取奖励
let rewardResult = await ladderBattleEndReward(roleId, roleName, sid, ladderData.historyRank, isSuccess, historyRank, 1);
let { battleGoods = [], breakGoods = [] } = rewardResult||{};
await checkTaskInLadderEnd(serverId, roleId, sid, isSuccess, historyRank, atkLadderMatch.rank);
if (isSuccess && (!rec.defenseInfo?.isRobot) && rec.defenseInfo.oldRank < rec.defenseInfo.newRank) await pushLadderIconShow(rec.roleId2, true);
return resResult(STATUS.SUCCESS, {...pick(result, ['rank', 'historyRank', 'challengeCnt','status', 'time', 'oppPlayers']), battleGoods, breakGoods});
}
// 8. 战5次(扫荡)
async battleSweep(msg: { roleId: string, rank: number, count: number }, session: BackendSession) {
let serverId = session.get('serverId');
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { roleId: targetRoleId, rank, count } = msg;
if(count > LADDER.LADDER_INITIAL_CHALLENGE_TIMES) {
return resResult(STATUS.LADDER_SWEEP_TIMES_OVER);
}
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
if(ladderData.rank >= rank) return resResult(STATUS.LADDER_RANK_ERR);
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
let update: LadderUpdateInter = {};
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.challengeCnt + count > LADDER.LADDER_CHALLENGE_FREE_TIMES + refOppObj.buyCnt) {
return resResult(STATUS.LADDER_CHALLENGE_CNT_MAX);
}
update.challengeCnt = refOppObj.challengeCnt + count;
ladderData = await LadderMatchModel.updateByRoleIdAndInclude(roleId, update);
// 获取奖励
let { battleGoods } = await ladderBattleEndReward(roleId, roleName, sid, rank, true, rank, count);
await checkTaskInLadderSweep(serverId, roleId, sid, count)
return resResult(STATUS.SUCCESS, {
challengeCnt: ladderData.challengeCnt,
battleGoods
});
}
// 9. 设置防守阵容
async saveDefense(msg: { warId: number, heroes: { actorId: number, ai: number, dataId: number, order: number, subHid?: number }[], combo: Combo[] }, session: BackendSession) {
let { warId, heroes, combo } = msg;
let roleId = session.get('roleId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let hids: number[] = heroes.map(cur => cur.actorId);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
for(let { actorId, subHid } of heroes) {
let dicHero = gameData.hero.get(actorId);
if(subHid && (!dicHero || dicHero.urType != 1)) return resResult(STATUS.HERO_CAN_NOT_SET_SUB);
if(subHid && hids.indexOf(subHid) != -1) return resResult(STATUS.HERO_SUB_DUPLICATE);
}
let dbHeroes = await HeroModel.findByHidRange(hids, roleId, '_id hid ce', true);
let defenseHeroes = heroes.map(cur => {
let dbHero = dbHeroes.find(ccur => ccur.hid == cur.actorId);
return dbHero && new LadderDefenseHero(cur, dbHero._id, dbHero.ce);
}).filter(cur => cur);
let defense = new LadderDefense(defenseHeroes, warId, combo);
ladderData = await LadderMatchModel.updateByRoleId(roleId, { defense, hasDefense: true });
// 返回
let result = new LadderDataReturn();
result.setLadderData(ladderData);
await saveLadderDefCeByData(roleId, ladderData);
return resResult(STATUS.SUCCESS, pick(result, 'defense'));
}
// 10. 刷新对手
async refreshOppPlayers(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let sid = session.get('sid');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData || !ladderData.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let update: LadderUpdateInter = {};
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.refOppCnt + 1 > LADDER.LADDER_REFRESH_TIMES) {
return resResult(STATUS.LADDER_REFRESH_CNT_MAX);
}
update.refOppCnt = refOppObj.refOppCnt + 1;
let oppPlayers = await refreshLadderEnemies(ladderData, update);
// 返回
return resResult(STATUS.SUCCESS, { refOppCnt: update.refOppCnt, oppPlayers });
}
// 11. 购买次数
async buyCnt(msg: { count: number }, session: BackendSession) {
let { count } = msg;
let roleId = session.get('roleId');
let sid = session.get('sid');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let update: LadderUpdateInter = {};
// 刷新次数
let refOppObj = refreshLadderDaily(ladderData);
if(refOppObj.shouldRefOpp) {
update = { ...refOppObj };
}
if(refOppObj.buyCnt + count > LADDER.LADDER_CHALLENGE_COST_TIMES) {
return resResult(STATUS.LADDER_BUY_MAX);
}
let consumes = getBuyCntCost(refOppObj.buyCnt, count);
if(!consumes) return resResult(STATUS.LADDER_BUY_MAX);
let consumeResult = await handleCost(roleId, sid, consumes||[], ITEM_CHANGE_REASON.LADDER_BUY_CNT);
if(!consumeResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
update.buyCnt = refOppObj.buyCnt + count;
ladderData = await LadderMatchModel.updateByRoleId(roleId, update);
// 返回
let result = new LadderDataReturn();
result.setLadderData(ladderData);
return resResult(STATUS.SUCCESS, pick(result, ['buyCnt', 'challengeCnt']));
}
// 12. 获取战报信息(2天内)
async getRec(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let list = await LadderMatchRecModel.findRecentRec(roleId, <number>getTimeFunM().getBeforeDay(2));
return resResult(STATUS.SUCCESS, {
list: list.map(rec => {
const { roleId1, battleCode, hasRpl, remoteUrl } = rec;
const rplFileUrl = battleCode && hasRpl ? remoteUrl : '';
return { ...rec, rplFileUrl };
}),
rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env'))
});
}
// debug接口
// 重置挑战次数 & 购买次数
async resetCnt(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
await LadderMatchModel.updateByRoleId(roleId, { refDaily: new Date(Date.now() - 86400000) });
return resResult(STATUS.SUCCESS);
}
async setMyRank(msg: { magicWord: string, rank: number }, session: BackendSession) {
const { magicWord, rank } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let atkLadderMatch = await LadderMatchModel.findByRoleId(roleId);
if(!atkLadderMatch || !atkLadderMatch.defense) return resResult(STATUS.LADDER_NOT_OPEN);
let myRank = atkLadderMatch.rank;
let defLadderMatch = await LadderMatchModel.findByRank(serverId, rank);
if(defLadderMatch) {
atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: myRank, historyRank: rank } }, { new: true }).lean();
defLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId: defLadderMatch.roleId }, { $set: { rank: myRank, oldRank: rank } }, { new: true }).lean();
} else {
atkLadderMatch = await LadderMatchModel.findOneAndUpdate({ roleId }, { $set: { rank, oldRank: atkLadderMatch.rank, historyRank: rank } }, { new: true }).lean();
}
await battleEndWhenChange(atkLadderMatch, defLadderMatch, true);
return resResult(STATUS.SUCCESS);
}
async setMyOpp(msg: { magicWord: string, oppRanks: number[] }, session: BackendSession) {
const { magicWord, oppRanks } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.WRONG_PARMS);
}
if(!isArray(oppRanks) || oppRanks.length <= 0) return resResult(STATUS.WRONG_PARMS);
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let ladderData = await LadderMatchModel.findByRoleId(roleId);
if(!ladderData) return resResult(STATUS.LADDER_NOT_OPEN);
let topTen = getNumberArr(1, 10);
let ranks = [...topTen, ...oppRanks];
let newRanks = uniqueArr(ranks.sort((a, b) => a - b));
await generateOppPlayers(newRanks, serverId, roleId);
return resResult(STATUS.SUCCESS);
}
async sendDailyReward(msg: { magicWord: string }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {
return resResult(STATUS.TOKEN_ERR);
}
let servers = await ServerlistModel.findByEnv(pinus.app.get('env'));
for(let { id } of servers) {
await sendLadderDailyReward(id);
}
return resResult(STATUS.SUCCESS)
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,399 +1,400 @@
import { STATUS } from './../../../consts/statusCode';
import { HANG_UP_CONSTS, ITEM_CHANGE_REASON, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE, REDIS_KEY } from './../../../consts';
import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from './../../../db/TowerTaskRec';
import { HangUpSpdUpRecModel } from './../../../db/HangUpSpdUpRec';
import { HangUpRecordModel } from './../../../db/HangUpRecord';
import { RoleModel } from './../../../db/Role';
import { TowerRecordModel, WarStatus } from './../../../db/TowerRecord';
import { Application, BackendSession } from 'pinus';
import { resResult, genCode, shouldRefresh } from '../../../pubUtils/util';
import { calcuHangUpReward, refreshTasks, treatTask, getRemainTime, getTowerStatus, getHungupRewards, getTasks, checkTaskRewards, getTowerTaskCostGold, getManyHangSpdUpCostGold, getTaskStatus, checkForbiddenChar, checkAndStartHungUp, createNewTowerRecord, getTowerRecByLv, getTowerStatusByWarId, getTowerHeroCe, getWarStatusByLv } from '../../../services/battleService';
import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService';
import { checkBattleHeroes } from '../../../services/normalBattleService';
import { gameData } from '../../../pubUtils/data';
import * as dicParam from '../../../pubUtils/dicParam';
import { HeroModel } from '../../../db/Hero';
import { vipCanSkipTower } from '../../../services/activity/monthlyTicketService';
import { pushTowerMsg } from '../../../services/sysChatService';
import { WarStar } from '../../../domain/dbGeneral';
import { ItemInter, RewardInter } from '../../../pubUtils/interface';
import { combineItems } from '../../../services/role/util';
import { checkTaskInSkipTower } from '../../../services/task/taskService';
import { Rank } from '../../../services/rankService';
import { checkPopUpCondition } from '../../../services/activity/popUpShopService';
import { isHeroHidden } from '../../../services/dataService';
export default function(app: Application) {
return new TowerBattleHandler(app);
}
export class TowerBattleHandler {
constructor(private app: Application) {
}
/**
* 获取天梯当前挑战状态
* @param session
*/
async getStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let role = await RoleModel.findByRoleId(roleId, 'roleId serverId towerLv towerReceived');
let data = await getTowerStatus(role);
return resResult(STATUS.SUCCESS, data);
}
/**
* 重置天梯当前层的挑战记录
* @param towerLv 要重置的天梯层数
* @param session
*/
async resetLv(msg: {towerLv: number}, session: BackendSession) {
let roleId = session.get('roleId');
let { towerLv } = await RoleModel.findByRoleId(roleId);
if (msg.towerLv !== towerLv) {
return resResult(STATUS.TOWER_RESET_ERR);
}
const record = await TowerRecordModel.resetRecordByLv(roleId, towerLv);
if (!record) {
return resResult(STATUS.TOWER_NOT_FOUND);
}
return resResult(STATUS.SUCCESS, {
roleId: record.roleId,
curLv: record.lv,
heroes: record.heroes,
warStatus: record.warStatus,
speedUpCnt: record.speedUpCnt,
speedUpTime: record.speedUpTime,
hangUpTime: record.hangUpTime,
passed: record.passed
});
}
/**
* 查询当前挂机可得奖励
* @param msg
* @param session
* @returns
*/
async checkHangUpRewards(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let result = await getHungupRewards(roleId);
if(!result) {
return resResult(STATUS.TOWER_HANG_UP_NOT_START);
}
return resResult(STATUS.SUCCESS, result);
}
/**
* 领取当前挂机可得奖励
* @param msg
* @param session
* @returns
*/
async recHangUpRewards(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let role = await RoleModel.findByRoleId(roleId);
const result = await calcuHangUpReward(role);
if(!result) {
return resResult(STATUS.TOWER_HANG_UP_NOT_START);
}
let { timeReward, endLv, endTime, deltaTime, needReceiveGoods } = result;
const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD);
await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods);
return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), goods });
}
/**
* 加速挂机
* @param {{speedUpCnt: number}} msg 加速次数
* @param session
* @returns
*/
async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { speedUpCnt } = msg;
const curTime = new Date();
let role = await RoleModel.findByRoleId(roleId);
let { hangUpSpdUpCnt, gold, lastSpdUpTime } = role;
if (shouldRefresh(lastSpdUpTime, curTime)) {
hangUpSpdUpCnt = 0;
}
if (speedUpCnt + hangUpSpdUpCnt > dicParam.TOWER_BOOST.TOWER_BOOSTTIME) {
return resResult(STATUS.TOWER_NOT_ENOUGH_HANG_UP_TIME)
}
const calResult = await calcuHangUpReward(role, true, msg.speedUpCnt, curTime);
if(!calResult) {
return resResult(STATUS.TOWER_HANG_UP_FAILED);
}
let { timeReward, endLv, deltaTime, needReceiveGoods } = calResult;
const costGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, msg.speedUpCnt);
if(costGold > gold) {
return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH);
}
await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.TOWER_HUNG_UP_SDP_UP)
const spdUpResult = await RoleModel.hangUpSpdUp(roleId, msg.speedUpCnt, curTime);
if (!spdUpResult) {
return resResult(STATUS.TOWER_HANG_UP_FAILED);
}
const spdUpRec = await HangUpSpdUpRecModel.updateRec(roleId, roleName, msg.speedUpCnt, endLv, needReceiveGoods);
const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD);
let nextCostGold = getManyHangSpdUpCostGold(spdUpResult.hangUpSpdUpCnt, 1);
return resResult(STATUS.SUCCESS, { goods, hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - spdUpResult.hangUpSpdUpCnt, nextCostGold, hangUpPassTime: Math.floor(deltaTime/1000), rewardLv: endLv, costGold });
}
async getTasks(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let result = await getTasks(roleId);
return resResult(STATUS.SUCCESS, result);
}
async refreshTasks(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let curTime = new Date();
let { towerLv, towerTaskRefTime, towerTaskReCnt=0 } = await RoleModel.findByRoleId(roleId);
if(towerTaskReCnt >= dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE) { // 付费刷新次数
return resResult(STATUS.TOWER_REF_CNT_NOT_ENOUGH);
}
let costGold = getTowerTaskCostGold(towerTaskReCnt, towerTaskRefTime);
let {gold} = await RoleModel.findByRoleId(roleId);
if(costGold > gold) {
return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH);
}
// 只刷掉当前面板上没有做派遣的任务
let batchCode = genCode(8);
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
for(let task of curTasks) {
if(task) batchCode = task.batchCode;
}
curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, curTasks);
let newRole = await RoleModel.increaseTowerRefCnt(roleId, 1);
let refRemainTime = getRemainTime(curTime);
let nextCostGold = getTowerTaskCostGold(newRole.towerTaskReCnt, newRole.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), costGold, nextCostGold, refRemainTime, towerTaskReCnt: newRole.towerTaskReCnt });
}
async sendTaskHero(msg: {batchCode: string, tasks: {taskCode: string, heroes: number[]}[]}, session: BackendSession) {
let roleId = session.get('roleId');
let batchCode = msg.batchCode;
const curTime = new Date();
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前一批的任务
if (!curTasks || curTasks.length == 0) {
return resResult(STATUS.TOWER_TASK_NOT_FOUND);
}
let usedHeroes: number[] = [], tasks: {taskCode:string, heroes: TaskHero[], completeTime: number}[] = [];
const tasksCode: string[] = [];
const taskMap = new Map<string, any>()
curTasks.forEach(task => {
let getStatusResult = getTaskStatus(task.status, task.completeTime, curTime);
if(getStatusResult.status == 1) {
for(let { seqId } of task.heroes) {
usedHeroes.push(seqId);
}
}
tasksCode.push(task.taskCode);
taskMap.set(task.taskCode, task);
batchCode = task.batchCode;
});
for (let { taskCode, heroes: seqIds } of msg.tasks) {
let curTask = taskMap.get(taskCode); // 数据库中,这个任务的数据
if(!curTask) {
return resResult(STATUS.TOWER_TASK_MISSING)
}
let dicTask = gameData.towerTask.get(curTask.taskId);
if (seqIds.length !== dicTask.actorNeeded) { // 武将数,从策划表中读取
return resResult(STATUS.TOWER_TASK_MAX_HERO);
}
let { isOK, heroes, hids } = await checkBattleHeroes(roleId, seqIds);
if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
if (tasksCode.indexOf(taskCode) === -1) {
return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND);
}
if (usedHeroes.length > 0) { // 是否在其他任务重使用了武将
let used = !!seqIds.find(seqId => usedHeroes.indexOf(seqId) !== -1);
if (used) {
return resResult(STATUS.TOWER_TASK_HERO_HAS_USED);
}
}
let taskHeroes = heroes.map(hero => {
return new TaskHero(hero);
});
tasks.push({ taskCode, heroes: taskHeroes, completeTime: dicTask.completeTime})
}
const recs = await TowerTaskRecModel.sendHeroes(roleId, batchCode, tasks, curTime,);
if (!recs || recs.length === 0) {
return resResult(STATUS.TOWER_TASK_SEND_ERR);
}
let role = await RoleModel.increaseTowerCnt(roleId, tasks.length)
let refRemainTime = getRemainTime(curTime);
curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold: costGold });
}
async settleTask(msg: {batchCode: string, taskCode: string}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
const { batchCode, taskCode } = msg;
let allFlag = !taskCode;
const curTime = new Date();
let tasks: TowerTaskRecType[] = [];
if(allFlag) {
tasks = await TowerTaskRecModel.getCurTasks(roleId);
} else {
let task = await TowerTaskRecModel.getTaskByCode(roleId, taskCode);
if(task) tasks.push(task);
}
if (!tasks || tasks.length == 0) {
return resResult(STATUS.TOWER_TASK_NOT_FOUND);
}
const checkResult = checkTaskRewards(batchCode, tasks);
if (!checkResult) {
return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE);
}
const { compTasks, rewards } = checkResult;
if(compTasks.length <= 0) return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE)
let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_TASK_REWARD);
await TowerTaskRecModel.finishTask(msg.batchCode, compTasks);
let refRemainTime = getRemainTime(curTime);
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
let role = await RoleModel.findByRoleId(roleId);
let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold });
}
async skipTower(msg: { toLv: number }, session: BackendSession) {
const { toLv } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let role = await RoleModel.findByRoleId(roleId);
let oldTowerLv = role.towerLv;
if(toLv <= oldTowerLv) return resResult(STATUS.TOWER_CANNOT_SKIP);
let dicTower = gameData.tower.get(oldTowerLv);
if(!dicTower.canSkip) {
return resResult(STATUS.TOWER_CANNOT_SKIP);
}
// 检查战力是否足够
let towerRec = await TowerRecordModel.getRecordByLv(roleId, oldTowerLv);
let heroes = await HeroModel.findByRole(roleId, [{ field: 'ce', sortBy: -1 }], 'hid ce job', true);
let newWarStar: WarStar[] = [], resultGoods: { towerLv: number, goods: { id: number, count: number }[] }[] = [], rewards: ItemInter[] = [];
for(let lv = oldTowerLv; lv < toLv; lv++) {
let dicTower = gameData.tower.get(lv);
let warArray = dicTower?.warArray||[];
let recommendCeSum = 0, heroesCeSum = 0;
for(let warId of warArray) {
if(!getTowerStatusByWarId(warId, towerRec?.warStatus)) {
let dicWar = gameData.war.get(warId);
recommendCeSum += dicWar.recommendedPower;
heroesCeSum += getTowerHeroCe(warId, heroes, towerRec.heroes);
newWarStar.push({ id: warId, warType: dicWar.warType, star: 0, stars: [] })
}
}
if(!vipCanSkipTower(recommendCeSum, heroesCeSum, role.vipStartTime)) {
return resResult(STATUS.TOWER_SKIP_POWER_NOT_ENOUGH)
}
resultGoods.push({ towerLv: lv, goods: dicTower.reward });
rewards.push(...dicTower.reward);
}
// 更新towerRecord
let warStatus: WarStatus[] = getWarStatusByLv(toLv);
await TowerRecordModel.skipTower(roleId, role.towerLv, toLv, warStatus);
await checkAndStartHungUp(roleId, roleName, role.towerLv);
// 更新玩家表
role = await RoleModel.setTowerLv(roleId, toLv, newWarStar);
await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_BATTLE_END);
pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1);
let data = await getTowerStatus(role);
// 更新redis
let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role);
await checkTaskInSkipTower(serverId, roleId, sid, role.towerLv);
await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: oldTowerLv - 1, newLv: role.towerLv - 1 })
return resResult(STATUS.SUCCESS, { ...data, resultGoods });
}
/**
* 获取节点奖励
* @param session
*/
async receiveBox(msg: { id: number }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { id } = msg; // id为0表示一键领取
let role = await RoleModel.findByRoleId(roleId, 'towerLv towerReceived');
if(!role) return resResult(STATUS.ROLE_NOT_FOUND);
let { towerLv, towerReceived = [] } = role;
let rewards: RewardInter[] = [], newReceived: number[] = [];
if(id == 0) {
for(let [ id, dicTowerGift ] of gameData.towerGift) {
if(towerLv > dicTowerGift.towerLv && towerReceived.indexOf(id) == -1) {
rewards.push(...dicTowerGift.reward);
newReceived.push(id);
}
}
if(newReceived.length <= 0) return resResult(STATUS.TOWER_BOX_NO_RECEIVE);
} else {
let dicTowerGift = gameData.towerGift.get(id);
if(!dicTowerGift) return resResult(STATUS.WRONG_PARMS);
if(towerLv <= dicTowerGift.towerLv) {
return resResult(STATUS.TOWER_LV_NOT_ENOUGH);
}
if(towerReceived.indexOf(id) != -1) {
return resResult(STATUS.TOWER_BOX_HAS_RECEIVED);
}
rewards.push(...dicTowerGift.reward);
newReceived.push(id);
}
role = await RoleModel.receiveTowerBox(roleId, newReceived);
let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.RECEIVE_TOWER_BOX);
return resResult(STATUS.SUCCESS, { goods, receivedBox: newReceived });
}
}
import { STATUS } from './../../../consts/statusCode';
import { HANG_UP_CONSTS, ITEM_CHANGE_REASON, MSG_SOURCE, POP_UP_SHOP_CONDITION_TYPE, REDIS_KEY } from './../../../consts';
import { TaskHero, TowerTaskRecModel, TowerTaskRecType } from './../../../db/TowerTaskRec';
import { HangUpSpdUpRecModel } from './../../../db/HangUpSpdUpRec';
import { HangUpRecordModel } from './../../../db/HangUpRecord';
import { RoleModel } from './../../../db/Role';
import { TowerRecordModel, WarStatus } from './../../../db/TowerRecord';
import { Application, BackendSession } from 'pinus';
import { resResult, genCode, shouldRefresh } from '@pubUtils/util';
import { calcuHangUpReward, refreshTasks, treatTask, getRemainTime, getTowerStatus, getHungupRewards, getTasks, checkTaskRewards, getTowerTaskCostGold, getManyHangSpdUpCostGold, getTaskStatus, checkForbiddenChar, checkAndStartHungUp, createNewTowerRecord, getTowerRecByLv, getTowerStatusByWarId, getTowerHeroCe, getWarStatusByLv } from '../../../services/battleService';
import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService';
import { checkBattleHeroes } from '../../../services/normalBattleService';
import { gameData } from '@pubUtils/data';
import * as dicParam from '@pubUtils/dicParam';
import { HeroModel } from '@db/Hero';
import { vipCanSkipTower } from '../../../services/activity/monthlyTicketService';
import { pushTowerMsg } from '../../../services/sysChatService';
import { WarStar } from '@domain/dbGeneral';
import { ItemInter, RewardInter } from '@pubUtils/interface';
import { combineItems } from '../../../services/role/util';
import { checkTaskInSkipTower } from '../../../services/task/taskService';
import { Rank } from '../../../services/rankService';
import { checkPopUpCondition } from '../../../services/activity/popUpShopService';
import { isHeroHidden } from '../../../services/dataService';
export default function(app: Application) {
return new TowerBattleHandler(app);
}
export class TowerBattleHandler {
constructor(private app: Application) {
}
/**
* 获取天梯当前挑战状态
* @param session
*/
async getStatus(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let serverId = session.get('serverId');
let role = await RoleModel.findByRoleId(roleId, 'roleId serverId towerLv towerReceived');
let data = await getTowerStatus(role);
return resResult(STATUS.SUCCESS, data);
}
/**
* 重置天梯当前层的挑战记录
* @param towerLv 要重置的天梯层数
* @param session
*/
async resetLv(msg: {towerLv: number}, session: BackendSession) {
let roleId = session.get('roleId');
let { towerLv } = await RoleModel.findByRoleId(roleId);
if (msg.towerLv !== towerLv) {
return resResult(STATUS.TOWER_RESET_ERR);
}
const record = await TowerRecordModel.resetRecordByLv(roleId, towerLv);
if (!record) {
return resResult(STATUS.TOWER_NOT_FOUND);
}
return resResult(STATUS.SUCCESS, {
roleId: record.roleId,
curLv: record.lv,
heroes: record.heroes,
warStatus: record.warStatus,
speedUpCnt: record.speedUpCnt,
speedUpTime: record.speedUpTime,
hangUpTime: record.hangUpTime,
passed: record.passed
});
}
/**
* 查询当前挂机可得奖励
* @param msg
* @param session
* @returns
*/
async checkHangUpRewards(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let result = await getHungupRewards(roleId);
if(!result) {
return resResult(STATUS.TOWER_HANG_UP_NOT_START);
}
return resResult(STATUS.SUCCESS, result);
}
/**
* 领取当前挂机可得奖励
* @param msg
* @param session
* @returns
*/
async recHangUpRewards(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let role = await RoleModel.findByRoleId(roleId);
const result = await calcuHangUpReward(role);
if(!result) {
return resResult(STATUS.TOWER_HANG_UP_NOT_START);
}
let { timeReward, endLv, endTime, deltaTime, needReceiveGoods } = result;
const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD);
await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods);
return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), goods });
}
/**
* 加速挂机
* @param {{speedUpCnt: number}} msg 加速次数
* @param session
* @returns
*/
async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { speedUpCnt } = msg;
const curTime = new Date();
let role = await RoleModel.findByRoleId(roleId);
let { hangUpSpdUpCnt, gold, lastSpdUpTime } = role;
if (shouldRefresh(lastSpdUpTime, curTime)) {
hangUpSpdUpCnt = 0;
}
if (speedUpCnt + hangUpSpdUpCnt > dicParam.TOWER_BOOST.TOWER_BOOSTTIME) {
return resResult(STATUS.TOWER_NOT_ENOUGH_HANG_UP_TIME)
}
const calResult = await calcuHangUpReward(role, true, msg.speedUpCnt, curTime);
if(!calResult) {
return resResult(STATUS.TOWER_HANG_UP_FAILED);
}
let { timeReward, endLv, deltaTime, needReceiveGoods } = calResult;
const costGold = getManyHangSpdUpCostGold(hangUpSpdUpCnt, msg.speedUpCnt);
if(costGold > gold) {
return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH);
}
await handleCost(roleId, sid, [getGoldObject(costGold)], ITEM_CHANGE_REASON.TOWER_HUNG_UP_SDP_UP)
const spdUpResult = await RoleModel.hangUpSpdUp(roleId, msg.speedUpCnt, curTime);
if (!spdUpResult) {
return resResult(STATUS.TOWER_HANG_UP_FAILED);
}
const spdUpRec = await HangUpSpdUpRecModel.updateRec(roleId, roleName, msg.speedUpCnt, endLv, needReceiveGoods);
const goods = await addItems(roleId, roleName, sid, timeReward, ITEM_CHANGE_REASON.TOWER_HUNG_UP_REWARD);
let nextCostGold = getManyHangSpdUpCostGold(spdUpResult.hangUpSpdUpCnt, 1);
return resResult(STATUS.SUCCESS, { goods, hangUpSpdUpCnt: dicParam.TOWER_BOOST.TOWER_BOOSTTIME - spdUpResult.hangUpSpdUpCnt, nextCostGold, hangUpPassTime: Math.floor(deltaTime/1000), rewardLv: endLv, costGold });
}
async getTasks(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let result = await getTasks(roleId);
return resResult(STATUS.SUCCESS, result);
}
async refreshTasks(msg: {}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let curTime = new Date();
let { towerLv, towerTaskRefTime, towerTaskReCnt=0 } = await RoleModel.findByRoleId(roleId);
if(towerTaskReCnt >= dicParam.TOWER_SEARCH.TOWER_SEARCH_REFRESHRULE) { // 付费刷新次数
return resResult(STATUS.TOWER_REF_CNT_NOT_ENOUGH);
}
let costGold = getTowerTaskCostGold(towerTaskReCnt, towerTaskRefTime);
let {gold} = await RoleModel.findByRoleId(roleId);
if(costGold > gold) {
return resResult(STATUS.TOWER_GOLD_NOT_ENOUGH);
}
// 只刷掉当前面板上没有做派遣的任务
let batchCode = genCode(8);
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
for(let task of curTasks) {
if(task) batchCode = task.batchCode;
}
curTasks = await refreshTasks(towerLv, batchCode, roleId, roleName, curTasks);
let newRole = await RoleModel.increaseTowerRefCnt(roleId, 1);
let refRemainTime = getRemainTime(curTime);
let nextCostGold = getTowerTaskCostGold(newRole.towerTaskReCnt, newRole.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), costGold, nextCostGold, refRemainTime, towerTaskReCnt: newRole.towerTaskReCnt });
}
async sendTaskHero(msg: {batchCode: string, tasks: {taskCode: string, heroes: number[]}[]}, session: BackendSession) {
let roleId = session.get('roleId');
let batchCode = msg.batchCode;
const curTime = new Date();
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前一批的任务
if (!curTasks || curTasks.length == 0) {
return resResult(STATUS.TOWER_TASK_NOT_FOUND);
}
let usedHeroes: number[] = [], tasks: {taskCode:string, heroes: TaskHero[], completeTime: number}[] = [];
const tasksCode: string[] = [];
const taskMap = new Map<string, any>()
curTasks.forEach(task => {
let getStatusResult = getTaskStatus(task.status, task.completeTime, curTime);
if(getStatusResult.status == 1) {
for(let { seqId } of task.heroes) {
usedHeroes.push(seqId);
}
}
tasksCode.push(task.taskCode);
taskMap.set(task.taskCode, task);
batchCode = task.batchCode;
});
for (let { taskCode, heroes: seqIds } of msg.tasks) {
let curTask = taskMap.get(taskCode); // 数据库中,这个任务的数据
if(!curTask) {
return resResult(STATUS.TOWER_TASK_MISSING)
}
let dicTask = gameData.towerTask.get(curTask.taskId);
if (seqIds.length !== dicTask.actorNeeded) { // 武将数,从策划表中读取
return resResult(STATUS.TOWER_TASK_MAX_HERO);
}
let { isOK, heroes, hids } = await checkBattleHeroes(roleId, seqIds);
if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
if(isHeroHidden(...hids)) return resResult(STATUS.HERO_IS_HIDDEN);
if (tasksCode.indexOf(taskCode) === -1) {
return resResult(STATUS.TOWER_TASK_CODE_NOT_FOUND);
}
if (usedHeroes.length > 0) { // 是否在其他任务重使用了武将
let used = !!seqIds.find(seqId => usedHeroes.indexOf(seqId) !== -1);
if (used) {
return resResult(STATUS.TOWER_TASK_HERO_HAS_USED);
}
}
let taskHeroes = heroes.map(hero => {
return new TaskHero(hero);
});
tasks.push({ taskCode, heroes: taskHeroes, completeTime: dicTask.completeTime})
}
const recs = await TowerTaskRecModel.sendHeroes(roleId, batchCode, tasks, curTime,);
if (!recs || recs.length === 0) {
return resResult(STATUS.TOWER_TASK_SEND_ERR);
}
let role = await RoleModel.increaseTowerCnt(roleId, tasks.length)
let refRemainTime = getRemainTime(curTime);
curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), refRemainTime, nextCostGold: costGold });
}
async settleTask(msg: {batchCode: string, taskCode: string}, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
const { batchCode, taskCode } = msg;
let allFlag = !taskCode;
const curTime = new Date();
let tasks: TowerTaskRecType[] = [];
if(allFlag) {
tasks = await TowerTaskRecModel.getCurTasks(roleId);
} else {
let task = await TowerTaskRecModel.getTaskByCode(roleId, taskCode);
if(task) tasks.push(task);
}
if (!tasks || tasks.length == 0) {
return resResult(STATUS.TOWER_TASK_NOT_FOUND);
}
const checkResult = checkTaskRewards(batchCode, tasks);
if (!checkResult) {
return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE);
}
const { compTasks, rewards } = checkResult;
if(compTasks.length <= 0) return resResult(STATUS.TOWER_TASK_CANNOT_RECEIVE)
let goods = await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_TASK_REWARD);
await TowerTaskRecModel.finishTask(msg.batchCode, compTasks);
let refRemainTime = getRemainTime(curTime);
let curTasks = await TowerTaskRecModel.getCurTasks(roleId); // 当前显示中的任务
let role = await RoleModel.findByRoleId(roleId);
let costGold = getTowerTaskCostGold(role.towerTaskReCnt, role.towerTaskRefTime);
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold });
}
async skipTower(msg: { toLv: number }, session: BackendSession) {
const { toLv } = msg;
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let serverId = session.get('serverId');
let sid = session.get('sid');
let role = await RoleModel.findByRoleId(roleId);
let oldTowerLv = role.towerLv;
if(toLv <= oldTowerLv) return resResult(STATUS.TOWER_CANNOT_SKIP);
let dicTower = gameData.tower.get(oldTowerLv);
if(!dicTower.canSkip) {
return resResult(STATUS.TOWER_CANNOT_SKIP);
}
// 检查战力是否足够
let towerRec = await TowerRecordModel.getRecordByLv(roleId, oldTowerLv);
let heroes = await HeroModel.findByRole(roleId, [{ field: 'ce', sortBy: -1 }], 'hid ce job', true);
let newWarStar: WarStar[] = [], resultGoods: { towerLv: number, goods: { id: number, count: number }[] }[] = [], rewards: ItemInter[] = [];
for(let lv = oldTowerLv; lv < toLv; lv++) {
let dicTower = gameData.tower.get(lv);
let warArray = dicTower?.warArray||[];
let recommendCeSum = 0, heroesCeSum = 0;
for(let warId of warArray) {
if(!getTowerStatusByWarId(warId, towerRec?.warStatus)) {
let dicWar = gameData.war.get(warId);
recommendCeSum += dicWar.recommendedPower;
heroesCeSum += getTowerHeroCe(warId, heroes, towerRec.heroes);
newWarStar.push({ id: warId, warType: dicWar.warType, star: 0, stars: [] })
}
}
if(!vipCanSkipTower(recommendCeSum, heroesCeSum, role.vipStartTime)) {
return resResult(STATUS.TOWER_SKIP_POWER_NOT_ENOUGH)
}
resultGoods.push({ towerLv: lv, goods: dicTower.reward });
rewards.push(...dicTower.reward);
}
// 更新towerRecord
let warStatus: WarStatus[] = getWarStatusByLv(toLv);
await TowerRecordModel.skipTower(roleId, role.towerLv, toLv, warStatus);
await checkAndStartHungUp(roleId, roleName, role.towerLv);
// 更新玩家表
role = await RoleModel.setTowerLv(roleId, toLv, newWarStar);
await addItems(roleId, roleName, sid, rewards, ITEM_CHANGE_REASON.TOWER_BATTLE_END);
pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, role.towerLv - 1);
let data = await getTowerStatus(role);
// 更新redis
let r = new Rank(REDIS_KEY.TOWER_RANK, { serverId });
await r.setRankWithRoleInfo(roleId, role.towerLv - 1, role.towerUpTime.getTime(), role);
await checkTaskInSkipTower(serverId, roleId, sid, role.towerLv);
await checkPopUpCondition(serverId, roleId, POP_UP_SHOP_CONDITION_TYPE.TOWER, { oldLv: oldTowerLv - 1, newLv: role.towerLv - 1 })
return resResult(STATUS.SUCCESS, { ...data, resultGoods });
}
/**
* 获取节点奖励
* @param session
*/
async receiveBox(msg: { id: number }, session: BackendSession) {
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let sid = session.get('sid');
let { id } = msg; // id为0表示一键领取
let role = await RoleModel.findByRoleId(roleId, 'towerLv towerReceived');
if(!role) return resResult(STATUS.ROLE_NOT_FOUND);
let { towerLv, towerReceived = [] } = role;
let rewards: RewardInter[] = [], newReceived: number[] = [];
if(id == 0) {
for(let [ id, dicTowerGift ] of gameData.towerGift) {
if(towerLv > dicTowerGift.towerLv && towerReceived.indexOf(id) == -1) {
rewards.push(...dicTowerGift.reward);
newReceived.push(id);
}
}
if(newReceived.length <= 0) return resResult(STATUS.TOWER_BOX_NO_RECEIVE);
} else {
let dicTowerGift = gameData.towerGift.get(id);
if(!dicTowerGift) return resResult(STATUS.WRONG_PARMS);
if(towerLv <= dicTowerGift.towerLv) {
return resResult(STATUS.TOWER_LV_NOT_ENOUGH);
}
if(towerReceived.indexOf(id) != -1) {
return resResult(STATUS.TOWER_BOX_HAS_RECEIVED);
}
rewards.push(...dicTowerGift.reward);
newReceived.push(id);
}
role = await RoleModel.receiveTowerBox(roleId, newReceived);
let goods = await addItems(roleId, roleName, sid, combineItems(rewards), ITEM_CHANGE_REASON.RECEIVE_TOWER_BOX);
return resResult(STATUS.SUCCESS, { goods, receivedBox: newReceived });
}
}