import { Application, BackendSession, HandlerService, } from 'pinus'; import { BattleRecordModel } from '../../../db/BattleRecord'; import { BattleSweepRecordModel } from '../../../db/BattleSweepRecord'; import { genCode } from '../../../pubUtils/util'; import { WAR_TYPE, EVENT_STATUS, FUNC_OPT_TYPE, MSG_SOURCE, REDIS_KEY, TASK_TYPE } from '../../../consts'; import { checkDaily, checkDailyAndIncrease } from '../../../services/dailyBattleService'; import { checkTowerWar, towerBattleEnd } from '../../../services/battleService'; import { WarReward } from '../../../services/warRewardService'; import { getAp, setAp } from '../../../services/actionPointService'; import { setBattleStatus, checkEventBattle } from '../../../services/eventSercive'; import { STATUS } from '../../../consts/statusCode'; import { resResult } from '../../../pubUtils/util'; import { RoleModel } from '../../../db/Role'; import { RScriptRecordModel } from '../../../db/RScriptRecord'; import { updateWarStar, checkBattleHeroes, roleLevelup, getBattleList } from '../../../services/normalBattleService'; import { checkDungeonNum, checkDungeonAndIncrease } from '../../../services/dungeonService'; import { switchOnFunc } from '../../../services/funcSwitchService'; import { gameData } from '../../../pubUtils/data'; import { pushMysteryFirstMsg, pushTowerMsg, pushVestigeFirstMsg } from '../../../services/chatService'; import { nowSeconds } from '../../../pubUtils/timeUtil'; import { Rank } from '../../../services/rankService'; import { checkTaskWithWar, checkTaskInBattleEnd, checkActivityTask } from '../../../services/taskService'; import { ActivitySelfServiceModel } from '../../../db/ActivitySelfService'; import { getSelfServiceShopActivityData } from '../../../services/activity/selfServiceShopActivityService'; import { challengeDailyGK } from '../../../services/activity/dailyGKService'; import { challengeNewHeroGK } from '../../../services/activity/newHeroGKService'; export default function (app: Application) { new HandlerService(app, {}); return new NormalBattleHandler(app); } export class NormalBattleHandler { constructor(private app: Application) { } // 获取关卡列表 async checkBattle(msg: { battleId: number, heroes: Array }, session: BackendSession) { const { battleId, heroes: seqIds = [] } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let warInfo = gameData.war.get(battleId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } let role = await RoleModel.findByRoleId(roleId, 'lv'); let apJson = await getAp(roleId, role.lv); let { ap } = apJson; if (ap < warInfo.cost) { return resResult(STATUS.BATTLE_ACTION_POINT_LACK); } // 前置关卡是否挑战过 let previousGk = warInfo.previousGk; if (previousGk) { let { warStar } = await RoleModel.findByRoleId(roleId); let preBattle = warStar.findIndex(cur => cur.id == previousGk); if (preBattle == -1) return resResult(STATUS.BATTLE_NEED_PREVIOUS_GK); } let { isOK, heroes } = await checkBattleHeroes(roleId, seqIds); if (!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND); const battleCode = genCode(8); // 关卡唯一值 let dailyNum = {}; let towerData = {}; let dungeonNum = {}; if (warInfo.warType == WAR_TYPE.DAILY) { let checkResult = await checkDaily(roleId, battleId, 1); if (checkResult.status == -1) { return checkResult.resResult } dailyNum = Object.assign(dailyNum, checkResult.data); } else if (warInfo.warType == WAR_TYPE.TOWER) { let checkResult = await checkTowerWar(roleId, battleId, seqIds, heroes); if (checkResult.status == -1) { return checkResult.resResult } towerData = Object.assign(towerData, checkResult.data); } else if (warInfo.warType == WAR_TYPE.EVENT) { // 记录事件状态 let eventStatus = session.get('eventStatus') || EVENT_STATUS.WAITING; let checkResult = await checkEventBattle(roleId, eventStatus, battleId, battleCode); if (checkResult.status == -1) { return checkResult.resResult } } else if (warInfo.warType == WAR_TYPE.MYSTERY || warInfo.warType == WAR_TYPE.MYSTERY_ELITE) { let checkResult = await checkDungeonNum(roleId, 1); if (checkResult.status == -1) { return checkResult.resResult } dungeonNum = Object.assign(dungeonNum, checkResult.data); } const BattleRecord = await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { roleId, roleName, battleId, status: 0, warName: warInfo.gk_name, warType: warInfo.warType, record: { heroes, seqIds } } }, true); let { status } = BattleRecord; return resResult(STATUS.SUCCESS, { battleId, battleCode, status, dailyNum, towerData, dungeonNum }); } // 关卡列表 async getBattleList(msg: { type: number }, session: BackendSession) { const { type } = msg; let roleId = session.get('roleId'); let role = await RoleModel.findByRoleId(roleId); let result = await getBattleList(role, type); return resResult(STATUS.SUCCESS, { list: result }); } // 关卡结算,记录使用的武将,获得奖励 async battleEnd(msg: { battleCode: string, battleId: number, isSuccess: boolean, star: number, heroes: Array, activityId: number, pageIndex: number }, session: BackendSession) { const { battleCode, battleId, isSuccess, heroes = [], star, activityId, pageIndex } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); const funcs: number[] = session.get('funcs'); let serverId = session.get('serverId'); let skipReward = false;//是否跳过奖励结算 let warInfo = gameData.war.get(battleId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } // 寻宝不使用通用战斗模块结算 if (warInfo.warType == WAR_TYPE.WARLOARDS) { return resResult(STATUS.BATTLE_END_WRONG_TYPE); } const BattleRecord = await BattleRecordModel.getBattleRecordByCode(battleCode, true); if (!BattleRecord || BattleRecord.status != 0) { return resResult(STATUS.BATTLE_STATUS_WRONG); } let flag = 1; // 对比hero信息 let { record: { heroes: dbHeroes, seqIds: dbSeqIds } } = BattleRecord; for (let seqId of dbSeqIds) { if (dbSeqIds.indexOf(seqId) == -1) flag = 0; } if (!flag) { return resResult(STATUS.BATTLE_INFO_VALIDATE_ERR); } let role = await RoleModel.findByRoleId(roleId, 'lv'); let apJson = await setAp(roleId, role.lv, isSuccess? -1 * warInfo.cost: 0, sid, funcs); // 扣除体力 if (!apJson) { return resResult(STATUS.BATTLE_ACTION_POINT_LACK); } let { warStar } = await RoleModel.findByRoleId(roleId); let warReward = new WarReward(roleId, roleName, sid, battleId, isSuccess); let dailyNum = {}; let towerStatus = null; let dungeonNum = {}; if (warInfo.warType == WAR_TYPE.DAILY) { let checkResult = await checkDailyAndIncrease(roleId, [{ id: battleId, star, warType: warInfo.warType }, ...warStar], battleId, 1, false); if (checkResult.status == -1) { return checkResult.resResult; } dailyNum = Object.assign(dailyNum, checkResult.data) } else if (warInfo.warType == WAR_TYPE.EVENT) { // 记录事件状态 await setBattleStatus(session, roleId, battleId, isSuccess, battleCode); } else if (warInfo.warType == WAR_TYPE.TOWER) { let towerEndResult = await towerBattleEnd(sid, funcs, roleId, serverId, battleCode, battleId, isSuccess, heroes); if (towerEndResult) { if (towerEndResult.status == -1) { return towerEndResult.resResult; } towerStatus = towerEndResult.data.towerStatus; if (towerEndResult.data.towerReward) warReward.setFixReward(towerEndResult.data.towerReward) pushTowerMsg(roleId, roleName, serverId, MSG_SOURCE.TOWER_SUC, towerEndResult.data.newRec.lv); } } else if (warInfo.warType == WAR_TYPE.MYSTERY || warInfo.warType == WAR_TYPE.MYSTERY_ELITE) { let checkResult = await checkDungeonAndIncrease(roleId, 1, false); let role = await RoleModel.saveDungeonHero(roleId, battleId, heroes, isSuccess); if (role) { let r = new Rank(REDIS_KEY.DUNGEON_RANK, { serverId }); await r.setRankWithRoleInfo(roleId, role.dungeonWarId, role.dungeonUpdatedAt, role); } if (checkResult.status == -1) { return checkResult.resResult; } dungeonNum = Object.assign(dungeonNum, checkResult.data) } else if (warInfo.warType == WAR_TYPE.NORMAL) { let role = await RoleModel.updateMainWarId(roleId, battleId, nowSeconds()); if (role) { let r = new Rank(REDIS_KEY.MAIN_RANK, { serverId }); await r.setRankWithRoleInfo(roleId, role.mainWarId, role.mainUpdatedAt, role); } } else if (warInfo.warType == WAR_TYPE.MAIN_ELITE) { let role = await RoleModel.updateMainEliteWarId(roleId, battleId, nowSeconds()); if (role) { let r = new Rank(REDIS_KEY.MAIN_ELITE_RANK, { serverId }); await r.setRankWithRoleInfo(roleId, role.mainEliteWarId, role.mainEliteUpdatedAt, role); await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.BATTLE_MAIN_ELITE, 1, { mainEliteWarId: battleId }) } } else if (warInfo.warType == WAR_TYPE.ACT_SELF_SHOP) { //糜家商队挑战成功后记录挑战次数 if (isSuccess) { let playerData = await getSelfServiceShopActivityData(serverId, roleId) await ActivitySelfServiceModel.addChallengeRecord(serverId, playerData.activityId, roleId, playerData.roundIndex, 1, new Date()) } } else if (warInfo.warType == WAR_TYPE.ACT_DAILY_GK) { if (isSuccess) { await challengeDailyGK(serverId, roleId, activityId, battleId) } } else if (warInfo.warType == WAR_TYPE.ACT_NEW_HERO_GK) { if (isSuccess) { let isFirst = await challengeNewHeroGK(serverId, roleId, activityId, pageIndex, battleId) skipReward = !isFirst; } } if (isSuccess) { // 挑战胜利 // 是否首通 let condition1 = warStar.find(cur => cur.id == battleId); if (!condition1) { await switchOnFunc(roleId, FUNC_OPT_TYPE.BATTLE_END, battleId, session); warReward.setCondition(0, true); pushMysteryFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); pushVestigeFirstMsg(roleId, roleName, serverId, warInfo.warType, warInfo.war_id); } // 是否首次3星 if (star == 3 && (!condition1 || condition1.star != 3)) { warReward.setCondition(1, true); } await updateWarStar(roleId, battleId, warInfo.warType, star); } let reward = null; if (!skipReward) { reward = await warReward.saveReward(1); } const updateResult = await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess ? 1 : 2, star, record: { heroes } } }, true); let { status } = updateResult; let actordata = await roleLevelup(roleId, isSuccess ? warInfo.kingExp : 0, session);// 主公升级经验 await checkTaskInBattleEnd(serverId, roleId, sid, funcs, battleId, dbHeroes, star); // 返回值: // towerStatus: false-本层未通过, true-本层已通过 return resResult(STATUS.SUCCESS, { battleCode, battleId, status, battleGoods: reward, towerStatus, dailyNum, dungeonNum, ...actordata }); } async battleSweep(msg: { battleId: number, count: number }, session: BackendSession) { const { battleId, count } = msg; let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); let serverId = session.get('serverId'); let funcs: number[] = session.get('funcs'); let warInfo = gameData.war.get(battleId); if (!warInfo) { return resResult(STATUS.BATTLE_MISS_INFO); } // 校验是否三星通关过 let { warStar } = await RoleModel.findByRoleId(roleId); let curWar = warStar.find(cur => cur.id == battleId); if (!curWar || curWar.star != 3) { return resResult(STATUS.BATTLE_SWEEP_CONDITION_STAR); } // 扣体力 let role = await RoleModel.findByRoleId(roleId, 'lv'); let apJson = await setAp(roleId, role.lv, -1 * warInfo.cost * count, sid, funcs); // 扣除体力 if (!apJson) { return resResult(STATUS.BATTLE_ACTION_POINT_LACK); } // 扫荡次数 let dailyNum = {}; let dungeonNum = {}; if (warInfo.warType == WAR_TYPE.DAILY) { let checkResult = await checkDailyAndIncrease(roleId, warStar, battleId, count, true); if (checkResult.status == -1) { return checkResult.resResult } dailyNum = Object.assign(dailyNum, checkResult.data) } else if (warInfo.warType == WAR_TYPE.MYSTERY || warInfo.warType == WAR_TYPE.MYSTERY_ELITE) { let checkResult = await checkDungeonAndIncrease(roleId, count, true); if (checkResult.status == -1) { return checkResult.resResult } dungeonNum = Object.assign(dungeonNum, checkResult.data) } // 发奖励 let warReward = new WarReward(roleId, roleName, sid, battleId, true); let result = await warReward.saveReward(count); let actordata = await roleLevelup(roleId, warInfo.kingExp * count, session)// 主公升级经验 // 扫荡记录 await BattleSweepRecordModel.saveBattleSweepRecordById(roleId, battleId, { $set: { roleName, warName: warInfo.gk_name, warType: warInfo.warType }, $inc: { count } }); // 任务 await checkTaskWithWar(roleId, sid, funcs, TASK_TYPE.BATTLE_MAIN_SWEEP, battleId, [], count, 0); //活动任务 await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.BATTLE_MAIN_SWEEP, count, { battleId }) return resResult(STATUS.SUCCESS, { battleId, count, battleGoods: result, dailyNum, dungeonNum, ...actordata }); } async saveScript(msg: { battleId: number, type: number, script: string }, session: BackendSession) { const { battleId, type, script } = msg; let roleId = session.get('roleId'); let warInfo = gameData.war.get(battleId); let result = await RScriptRecordModel.setScript(roleId, battleId, warInfo.warType, type, script); if (result) { if (!result.scriptBefore) result.scriptBefore = ''; if (!result.scriptAfter) result.scriptAfter = ''; return resResult(STATUS.SUCCESS, result); } else { console.error('script not created'); return resResult(STATUS.INTERNAL_ERR); } } async getScriptByBattle(msg: { battleIds: Array }, session: BackendSession) { const { battleIds } = msg; let roleId = session.get('roleId'); let list = new Array(); for (let battleId of battleIds) { let result = await RScriptRecordModel.findbyRoleAndBattle(roleId, battleId); if (result) { let { scriptBefore = '', scriptAfter = '' } = result; list.push({ battleId, scriptBefore, scriptAfter }); } else { list.push({ battleId, scriptBefore: '', scriptAfter: '' }); } } return resResult(STATUS.SUCCESS, { list }); } }