415 lines
18 KiB
TypeScript
415 lines
18 KiB
TypeScript
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, 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';
|
|
|
|
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 { 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 }>, enemies: Array<{ dataId: number, hp: number, ap: number }>, star: number, stars: number[] }, session: BackendSession) {
|
|
|
|
const { expeditionCode, battleCode, battleId, expeditionId, isSuccess, heroes = [], star, stars = [], enemies } = 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 }
|
|
}, 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);
|
|
}
|
|
}
|