1322 lines
62 KiB
TypeScript
1322 lines
62 KiB
TypeScript
import { Application, BackendSession, pinus, HandlerService, } from 'pinus';
|
||
import { RougelikeRecordModel } from '../../../db/RougelikeRecord';
|
||
import { genCode, getRandEelmWithWeight, resResult } from '../../../pubUtils/util';
|
||
import { COLLECTION_TYPE, ITEM_CHANGE_REASON, REST_POINT_TYPE, ROUGE_LIKE_CARD_TYPE, ROUGE_LIKE_CHOOSE_REWARD, ROUGE_LIKE_NODE_TYPE, ROUGE_LIKE_STATUS, TASK_ROUGE_CARD_TYPE, TASK_TYPE } from '../../../consts';
|
||
import { Quest, RestPoint, RougelikeRecordDetailModel } from '../../../db/RougelikeRecordDetail';
|
||
import { STATUS } from '../../../consts/statusCode';
|
||
import { RougelikeCardModel, RougelikeCardPara, RougelikeCardType } from '../../../db/RougelikeCard';
|
||
import { Card, RougelikeCharaModel, RougelikeCharaPara, RougelikeCharaType } from '../../../db/RougelikeChara';
|
||
import { CollectionReturnParam, CommonCard, CommonChara, RewardInter, RewardOption, RougeDamageInter, SlotCard, layerNode } from '../../../pubUtils/interface';
|
||
import { clone } from 'underscore';
|
||
import { RougelikeScoreModel } from '../../../db/RougelikeScore';
|
||
import { RougelikeTechModel } from '../../../db/RougelikeTech';
|
||
import { RougelikeCollectionModel } from '../../../db/RougelikeCollection';
|
||
import { RougelikeLayerModel, RougelikeLayerType } from '../../../db/RougelikeLayer';
|
||
import { RoleModel } from '../../../db/Role';
|
||
import { gameData } from '../../../pubUtils/data';
|
||
import { chooseNode, getCardCount, getGame, getInitCharaCard, getLayerNodeReward, getLayerRewardOneData, getMap, getMaxHp, getRandomSpirit, getRougeData, repaireSendScoreReward, updateChalleng, updateMaxHp } from '../../../services/battle/rougeService';
|
||
import { checkPreRougeTech, getCurTechData, updateEffectId } from '../../../services/battle/rougeTechService';
|
||
import { BattleRecordModel } from '../../../db/BattleRecord';
|
||
import { HeroModel } from '../../../db/Hero';
|
||
import { ROUGELIKE } from '../../../pubUtils/dicParam';
|
||
import { HandleAddCard, addSameTypeCollect, addSingleCollect, formateCharasOrCards } from '../../../services/battle/rougeCollectService';
|
||
import { DicRougePassiveCollect } from '../../../pubUtils/dictionary/DicRougePassiveCollect';
|
||
import { DicRougeHolyCard } from '../../../pubUtils/dictionary/DicRougeHolyCard';
|
||
import { DicRougeSkillCard } from '../../../pubUtils/dictionary/DicRougeSkillCard';
|
||
import { DicRougeOptionGroup } from '../../../pubUtils/dictionary/DicRougeOptionGroup';
|
||
import { addItems, getRougeTechScoreObject, handleCost } from '../../../services/role/rewardService';
|
||
import { getEffectWhenGameStart, getCharaHp, getAddCoin, getNoBossRecoveryHp, getBattleRecoveryNum, getRecoveryExtendHp, getTrainCardDiscount, checkCanChooseSkillCard, checkCanReRandomReward } from '../../../services/battle/rougeEffectService';
|
||
import { RougelikeExtendModel } from '../../../db/RougelikeExtend';
|
||
import * as util from 'util';
|
||
import { DicRougePassiveCard } from '../../../pubUtils/dictionary/DicRougePassiveCard';
|
||
import { checkTask } from '../../../services/task/taskService';
|
||
|
||
export default function (app: Application) {
|
||
new HandlerService(app, {});
|
||
return new RougeHandler(app);
|
||
}
|
||
|
||
export class RougeHandler {
|
||
constructor(private app: Application) {
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取大界面数据(即进入游戏获取当前是否有进行中的一场数据)
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async getData(msg: {}, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
|
||
let data = await getRougeData(roleId);
|
||
return resResult(STATUS.SUCCESS, data);
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取一场试炼正在进行中的游戏数据
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async getGame(msg: {}, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
|
||
return resResult(STATUS.SUCCESS, { ...await getGame(roleId) })
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 获取初始角色卡
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async getInitCharaCard(msg: { type: number, grade: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let sid = session.get('sid');
|
||
|
||
const { type, grade } = msg;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS)
|
||
// 存在一场正在进行中,不能开启新一场
|
||
if (dbRecord) return resResult(STATUS.ROUGELIKE_GAME_PLAYING);
|
||
|
||
let typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade);
|
||
if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE);
|
||
|
||
const { lv = 0 } = await RoleModel.findByRoleId(roleId, 'lv');
|
||
if (lv < (typeGradeData.lvLimit || 0)) return resResult(STATUS.LIMIT_LV);
|
||
|
||
// 开启新一场
|
||
const gameCode = genCode(8);
|
||
|
||
const charaCards = getInitCharaCard() || [];
|
||
|
||
let handleAddFun = new HandleAddCard(session, gameCode);
|
||
for (let ele of charaCards) {
|
||
handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []);
|
||
}
|
||
let result = await handleAddFun.save();
|
||
await RougelikeRecordModel.updateByGameCode(gameCode, {
|
||
$set: {
|
||
roleId, grade, type, authorType: 0, curLayer: 0,
|
||
maxLayer: typeGradeData.layerCount, status: 0, takeoutReward: [],
|
||
},
|
||
$inc: { score: 0, coin: 0, techScore: 0 }
|
||
})
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, ...result })
|
||
}
|
||
|
||
/**
|
||
* 角色卡刷新
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async refreshInitCharaCard(msg: { gameCode: string }, session: BackendSession) {
|
||
const roleId = session.get('roleId');
|
||
|
||
const { gameCode } = msg;
|
||
|
||
let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
const { type = 0, grade = 0 } = dbRecord;
|
||
|
||
await RougelikeCharaModel.deleteCharaByRoleId(roleId);
|
||
const charaCards = getInitCharaCard() || [];
|
||
let handleAddFun = new HandleAddCard(session, gameCode);
|
||
for (let ele of charaCards) {
|
||
handleAddFun.pushChara(ele.id, await getMaxHp(roleId, gameCode, ele.id, type, grade), []);
|
||
}
|
||
let result = await handleAddFun.save();
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, charas: result?.addCharas || [] })
|
||
}
|
||
|
||
|
||
/**
|
||
* 开启一场游戏
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async startGame(msg: { gameCode: string, authorType: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let sid = session.get('sid');
|
||
let serverId = session.get('serverId');
|
||
|
||
const { gameCode, authorType } = msg;
|
||
|
||
// 检测流派
|
||
const authorTypeData = gameData.rougeAuthorType.get(authorType);
|
||
if (!authorTypeData) return resResult(STATUS.NO_AUTHOR_TYPE);
|
||
|
||
let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
// 未选角色
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME)
|
||
// 存在一场正在进行中,不能开启新一场
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.CHOOSECHARA) return resResult(STATUS.ROUGELIKE_GAME_PLAYING);
|
||
|
||
const { type, grade, curLayer, maxLayer, } = dbRecord
|
||
const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade);
|
||
if (!typeGradeData) return resResult(STATUS.NO_TYPE_GRADE);
|
||
|
||
const typeGradeByIdData = gameData.rougeTypeGradeById.get(typeGradeData.limitId);
|
||
if (typeGradeByIdData) {
|
||
const dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.limitId)
|
||
if (!dbExtend) return resResult(STATUS.TYPE_UNLOCK);
|
||
}
|
||
|
||
let nodes = getMap(typeGradeData.layerPlan, typeGradeData.layerCount);
|
||
|
||
await RougelikeLayerModel.bulkWriteUpdate(nodes.map(cur => { return { ...cur, gameCode, roleId, status: 0 }; }));
|
||
await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { authorType, status: ROUGE_LIKE_STATUS.INPROGRESS } });
|
||
|
||
let { addCoin, cardIds } = await getEffectWhenGameStart(roleId, gameCode, authorType);
|
||
dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: addCoin, coinTotal: addCoin } });
|
||
//任务
|
||
if (addCoin > 0) {
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin });
|
||
}
|
||
|
||
|
||
|
||
const charas: CommonChara[] = formateCharasOrCards(await RougelikeCharaModel.findByGameCode(gameCode), ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || [];
|
||
let handleAddFun = new HandleAddCard(session, gameCode);
|
||
handleAddFun.pushHolyCards(cardIds);
|
||
let result = await handleAddFun.save();
|
||
result = await handleAddFun.getHolyEffect();
|
||
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, grade, coin: dbRecord.coin, coinTotal: dbRecord.coinTotal, type, authorType, curLayer, maxLayer, nodes, charas: [...charas, ...result.addCharas], cards: result.addCards })
|
||
|
||
}
|
||
|
||
/**
|
||
* 结束游戏
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async gameEnd(msg: { gameCode: string }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
let serverId = session.get('serverId');
|
||
|
||
const { gameCode } = msg;
|
||
let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
let { type, grade, status = 0, takeoutReward = [], hasReceivedTakeout = false, curLayer = 0, } = dbRecord;
|
||
if (status == ROUGE_LIKE_STATUS.SUCCESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
status = ROUGE_LIKE_STATUS.SUCCESS;
|
||
|
||
const dbLayers = await RougelikeLayerModel.findByGameCode(gameCode);
|
||
|
||
let takeoutRewardMap = takeoutReward.reduce((map, cur) => { map.set(cur.id, cur.count); return map; }, new Map<number, number>());
|
||
let spiritIds: number[] = [];
|
||
let addScore = 0, addTech = 0, isPass = true;
|
||
if (dbLayers.length == 0) isPass = false;
|
||
for (const { layer, hasPass = false, layerNodes } of dbLayers) {
|
||
if (layer > dbRecord.curLayer) {
|
||
isPass = false;
|
||
continue;
|
||
};
|
||
const layerNodeOne = layerNodes.find(cur => cur.isChoose == 1);
|
||
let nodeType = layerNodeOne?.type || 0;
|
||
const detailCode = layerNodeOne?.detailCode;
|
||
|
||
//忽略挑战关
|
||
if (!hasPass && nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) {
|
||
isPass = false;
|
||
continue;
|
||
}
|
||
if (nodeType == ROUGE_LIKE_NODE_TYPE.QUEST_POINT) {
|
||
const dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode)
|
||
nodeType = dbDetail?.questType || 0;
|
||
}
|
||
const layerReward = getLayerRewardOneData(type, grade, layer, nodeType);
|
||
const { takeoutReward = [], score = 0, tech = 0, spiritPlan } = clone(layerReward);
|
||
addScore += score, addTech += tech;
|
||
for (const { id, count } of takeoutReward) takeoutRewardMap.set(id, takeoutRewardMap.get(id) || 0 + count);
|
||
for (const { id, count } of spiritPlan) { spiritIds.push(...getRandomSpirit(id, count)); }
|
||
}
|
||
let spiritMap = new Map<number, RewardInter>();
|
||
spiritIds.forEach((spiritId) => {
|
||
spiritMap.set(spiritId, { id: spiritId, count: (spiritMap.get(spiritId)?.count || 0) + 1 });
|
||
})
|
||
|
||
takeoutReward = [...Array.from(takeoutRewardMap, ([id, count]) => ({ id, count })), ...spiritMap.values()];
|
||
|
||
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
dbRecord = await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { status, takeoutReward }, $inc: { score: addScore, techScore: addTech } });
|
||
|
||
let { score = 0, techScore = 0 } = dbRecord;
|
||
let dbScore = await RougelikeScoreModel.incScore(roleId, score);
|
||
let goods = await addItems(roleId, roleName, sid, [getRougeTechScoreObject(techScore)], ITEM_CHANGE_REASON.ROUGE_TECH_SCORE);
|
||
|
||
let firstReward = [];
|
||
if (isPass) {
|
||
const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade);
|
||
if (!typeGradeData || !typeGradeData.id) return resResult(STATUS.NO_TYPE_GRADE);
|
||
let dbExtend = await RougelikeExtendModel.findByRoleIdAndLimitId(roleId, typeGradeData.id);
|
||
if ((dbExtend?.limitId || 0) != typeGradeData.id) {
|
||
firstReward = await addItems(roleId, roleName, sid, typeGradeData?.firstReward || [], ITEM_CHANGE_REASON.ROUGE_FIRST_REWARD);
|
||
await RougelikeExtendModel.update(roleId, typeGradeData.id, firstReward, gameCode);
|
||
}
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.FUND_ROUGE, { rougeId: typeGradeData.id, count: 1 });
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GAME_COUNT, { count: 1 });
|
||
}
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
gameCode, goods, score, techScore, hasReceivedTakeout, firstReward,
|
||
takeoutReward, weeklyScore: dbScore?.score || 0, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0
|
||
});
|
||
|
||
}
|
||
|
||
/**
|
||
* 选择外带奖励
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async takeoutReward(msg: { gameCode: string }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
const { gameCode } = msg;
|
||
let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
let { takeoutReward, hasReceivedTakeout } = dbRecord;
|
||
if (hasReceivedTakeout) return resResult(STATUS.ROUGELIKE_TAKEOUT_HAS_RECEIVED);
|
||
|
||
let dbScore = await RougelikeScoreModel.receiveTakeoutReward(roleId, ROUGELIKE.TAKEOUT_REWARD_CNT);
|
||
if (!dbScore) return resResult(STATUS.ROUGELIKE_TAKEOUT_CNT_NOT_ENOUGH);
|
||
|
||
dbRecord = await RougelikeRecordModel.takeout(gameCode);
|
||
|
||
let goods = await addItems(roleId, roleName, sid, takeoutReward, ITEM_CHANGE_REASON.ROUGE_TAKE_OUT_REWARD)
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, hasReceivedTakeout: dbRecord?.hasReceivedTakeout || false, takeoutRewardCnt: dbScore?.takeoutRewardCnt || 0, goods });
|
||
}
|
||
|
||
/**
|
||
* 选择关卡节点
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async chooseNode(msg: { gameCode: string, layer: number, detailCode: string }, session: BackendSession) {
|
||
let chooseNodeStartTime = Date.now();
|
||
|
||
let roleId = session.get('roleId');
|
||
const { gameCode, layer, detailCode } = msg;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
const { curLayer, maxLayer, type, grade } = dbRecord;
|
||
|
||
if (layer < curLayer || layer > maxLayer) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
|
||
let dbCurLayer = {} as RougelikeLayerType, dbPreLayer = {} as RougelikeLayerType;
|
||
let dbLayerNodes = await RougelikeLayerModel.findByGameCodeAndLayers(gameCode, [layer, layer - 1]);
|
||
|
||
if (!dbLayerNodes) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
for (let val of dbLayerNodes) {
|
||
if (val.layer == layer) {
|
||
if (val.hasPass) return resResult(STATUS.NODE_NO_CHOOSE);//当前关完成
|
||
dbCurLayer = val;
|
||
}
|
||
// 注意过滤挑战点
|
||
if ((val.layer || 0) == layer - 1 && layer - 1 > 0) {
|
||
let dbDetail = await RougelikeRecordDetailModel.findByGameCodeAndLayer(gameCode, layer - 1);
|
||
if (!val.hasPass && (!dbDetail || dbDetail.nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE)) return resResult(STATUS.NODE_NO_CHOOSE);//前一关未完成
|
||
dbPreLayer = val;
|
||
}
|
||
}
|
||
|
||
let dbIsChoose = dbCurLayer.layerNodes.find(cur => cur.isChoose == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE);
|
||
if (dbIsChoose && dbIsChoose.detailCode != detailCode) return resResult(STATUS.NODE_NO_CHOOSE); //该层已经选择过一关卡,不能再次选择其他关卡
|
||
let dbCurLayerChooseNode: layerNode = dbCurLayer.layerNodes.find(cur => cur.detailCode == detailCode);
|
||
if (!dbCurLayerChooseNode) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
if (dbPreLayer && Object.keys(dbPreLayer).length > 0) {
|
||
let dbPreLayerChooseNode = dbPreLayer.layerNodes.find(cur => cur.isChoose != 0);
|
||
if (dbCurLayerChooseNode.preNodeIndexs.indexOf(dbPreLayerChooseNode.index) == -1) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
}
|
||
|
||
|
||
const curNode = await chooseNode(dbRecord, dbCurLayerChooseNode, layer)
|
||
|
||
console.log('*********************************nodeType=%s, chooseNodeTime=%s', curNode?.nodeType, Date.now() - chooseNodeStartTime);
|
||
|
||
return resResult(STATUS.SUCCESS, { detailCode, layer, curNode })
|
||
}
|
||
|
||
// 挑战关卡
|
||
async checkBattle(msg: { gameCode: string, detailCode: string, warId: number, charaCodes: string[] }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
|
||
const { gameCode, detailCode, warId, charaCodes } = msg;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
let { status = 0, rewards, layer, nodeType, warId: detailWarId = 0 } = dbDetail;
|
||
|
||
if (status != 0 || warId != detailWarId) return resResult(STATUS.WAR_NO_CHOOSE);
|
||
|
||
let dicWar = gameData.war.get(detailWarId);
|
||
if (!dicWar) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
const battleCode = genCode(8); // 关卡唯一值
|
||
const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, charaCodes);
|
||
if (!dbCharas || dbCharas.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
await BattleRecordModel.updateBattleRecordByCode(battleCode, {
|
||
$set: {
|
||
roleId, roleName, battleId: warId, status: 0, warName: dicWar.gk_name, warType: dicWar.warType,
|
||
record: {
|
||
rougeOriginal: dbCharas.map(cur => {
|
||
const { charaId, cards = [], hp = 0, ap = 0, shield = 0, roundSkill = 0, apSkill = 0 } = cur;
|
||
return { charaId, cards, hp, ap, roundSkill, apSkill }
|
||
})
|
||
}
|
||
}
|
||
}, true);
|
||
return resResult(STATUS.SUCCESS, { gameCode, battleCode });
|
||
}
|
||
|
||
|
||
/**
|
||
* 结束关卡
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async battleEnd(msg: { gameCode: string, detailCode: string, battleCode: string, warId: number, status: number, round: number, rougeDamage: RougeDamageInter[] }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let roleName = session.get('roleName');
|
||
let sid = session.get('sid');
|
||
let serverId = session.get('serverId');
|
||
|
||
let { gameCode, detailCode, battleCode, warId, status, round, rougeDamage } = msg;
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail || (dbDetail.warId || 0) != warId || warId == 0 || (dbDetail.status || 0) != 0) return resResult(STATUS.WAR_NO_CHOOSE);
|
||
let { layer, nodeType, questType = 0 } = dbDetail;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
const dbCharas = await RougelikeCharaModel.findByCodes(gameCode, rougeDamage.map(cur => { return cur.charaCode }));
|
||
if (!dbCharas || dbCharas.length == 0 || dbCharas.length != rougeDamage.length) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
await BattleRecordModel.findOneAndUpdate({ battleCode }, {
|
||
$set: { status, 'record.round': round, 'record.rougeDamage': rougeDamage, }
|
||
}, { new: true, upsert: true }).lean(true);
|
||
|
||
const dbCharaMap = dbCharas.reduce((result, cur) => { result.set(cur.charaCode, { ...cur }); return result; }, new Map<string, RougelikeCharaType>());
|
||
|
||
let isAp: boolean = false, isRound: boolean = false, arrAuthorType: number[] = [], isHpZero = false;
|
||
for (let obj of rougeDamage) {
|
||
if (obj.isAp) isAp = true;
|
||
if (obj.isRound) isRound = true;
|
||
const chara = dbCharaMap.get(obj.charaCode);
|
||
if (!chara) return resResult(STATUS.BATTLE_ABNORMAL)
|
||
obj.maxHp = (chara.maxHp || 0);
|
||
|
||
if (!chara.cards || chara.cards.length == 0) console;
|
||
for (const { cardId } of chara.cards) {
|
||
const passiveCardData = gameData.rougePassiveCard.get(cardId);
|
||
if (nodeType == ROUGE_LIKE_NODE_TYPE.BOSS && passiveCardData && passiveCardData.authorType) arrAuthorType.push(passiveCardData.authorType);
|
||
}
|
||
if (!obj.hp || obj.hp == 0) isHpZero = true;
|
||
}
|
||
await updateChalleng(dbRecord, roleId, sid, gameCode, layer, rougeDamage, isAp, isRound);
|
||
|
||
let updateCharas: RougelikeCharaPara[] = [], charas: CommonChara[] = [];
|
||
|
||
|
||
let recoveryHp = false;
|
||
if (status != 1 && nodeType != ROUGE_LIKE_NODE_TYPE.BOSS && isHpZero) {
|
||
recoveryHp = await getNoBossRecoveryHp(roleId, gameCode);
|
||
if (recoveryHp) status = 1;
|
||
}
|
||
|
||
let hpRatio = 0;
|
||
if (status == 1) {
|
||
hpRatio = await getCharaHp(roleId, gameCode);
|
||
}
|
||
const minHp = rougeDamage.reduce((min, cur) => { return Math.min(min, cur.hp); }, Infinity);
|
||
let recoveryNum = 0;
|
||
if (minHp == 0) recoveryNum = await getBattleRecoveryNum(roleId, gameCode);
|
||
|
||
|
||
let updateCharasMap = new Map();
|
||
for (let { charaCode, hp, ap, shield, others } of rougeDamage) {
|
||
const chara = dbCharaMap.get(charaCode);
|
||
if (!chara) return resResult(STATUS.BATTLE_ABNORMAL)
|
||
if (chara.maxHp < hp) hp = chara.maxHp;
|
||
|
||
if (recoveryHp && hp == 0) hp = chara.maxHp;
|
||
if (hpRatio > 0 && hp != 0) hp = Math.min(Math.floor(hp + (chara.maxHp * hpRatio / 100)), chara.maxHp);
|
||
|
||
if ((recoveryNum--) > 0 && hp == 0) { hp = chara.maxHp; }
|
||
|
||
charas.push({ charaCode, charaId: chara.charaId, seqId: chara.seqId, cards: chara.cards, hp, maxHp: chara.maxHp, ap, shield, others, apSkill: chara.apSkill, roundSkill: chara.roundSkill })
|
||
updateCharas.push({ gameCode, charaCode, hp, ap, shield, others });
|
||
updateCharasMap.set(charaCode, { hp, ap, shield, others });
|
||
}
|
||
|
||
let incCoin = 0;
|
||
if (status == 1) {
|
||
let { coinRatio, coinAdd } = await getAddCoin(roleId, gameCode, nodeType);
|
||
let newNodeType = nodeType;
|
||
if (questType > 0) newNodeType = questType;
|
||
const layerReward = getLayerRewardOneData(dbRecord.type, dbRecord.grade, layer, newNodeType);
|
||
incCoin = Math.floor((layerReward.coin || 0) * (1 + coinRatio / 100) + coinAdd);
|
||
await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } });
|
||
}
|
||
|
||
// let coinReward = rewards.find(cur => cur.rewardType == 0);
|
||
// if (coinReward) coinReward.chooseNum = Math.floor(coinReward.chooseNum * (1 + coinRatio / 100) + coinAdd);
|
||
// if (coinRatio != 0 || coinAdd != 0) {
|
||
// await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.rewardType': 0 }, { 'rewards.$.chooseNum': coinReward.chooseNum, }, { new: true, upsert: true }).lean(true);
|
||
// }
|
||
|
||
await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } })
|
||
|
||
if (incCoin > 0) {
|
||
charas = await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade, updateCharasMap)
|
||
|
||
//任务
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_GET_COIN, { addCoin: incCoin });
|
||
|
||
} else {
|
||
await RougelikeCharaModel.bulkWriteUpdate(updateCharas);
|
||
}
|
||
|
||
if (status == 1 && arrAuthorType.length > 0 && arrAuthorType.every(cur => cur == arrAuthorType[0])) {
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_BOSS_PASS, { authorType: arrAuthorType[0], count: 1 });
|
||
}
|
||
|
||
return resResult(STATUS.SUCCESS, { status, gameCode, detailCode, charas, incCoin });
|
||
}
|
||
|
||
// 重置
|
||
async reRandomReward(msg: { gameCode: string, detailCode: string, rewardType: number }, session: BackendSession) {
|
||
const roleId: string = session.get('roleId');
|
||
const { gameCode, detailCode, rewardType } = msg;
|
||
|
||
// 检查数量
|
||
let { canReRandom, costCoin } = await checkCanReRandomReward(roleId, gameCode, rewardType);
|
||
if (!canReRandom) return resResult(STATUS.ROUGE_TECH_NOT_UNLOCKED);
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
let dbDetailReward = dbDetail.rewards.find(cur => cur.rewardType == rewardType);
|
||
if (!dbDetailReward || dbDetailReward.reRandRewardCnt > 0) return resResult(STATUS.ROUGE_RE_RANDOM_CNT_OVER);
|
||
|
||
const typeGradeData = gameData.rougeTypeGrade.get(dbRecord.type + '_' + dbRecord.grade);
|
||
const nodeData = gameData.rougeNode.get(dbDetail.nodeId);
|
||
if (!typeGradeData || !nodeData) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + dbDetail.layer);
|
||
if (!layerPlanData) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
let costResult = await RougelikeRecordModel.costCoin(gameCode, costCoin);
|
||
if (!costResult) return resResult(STATUS.COIN_NOT_ENOUGH);
|
||
|
||
let replaceReward = await getLayerNodeReward(roleId, gameCode, dbRecord.authorType, dbDetail.nodeId, layerPlanData.rewardPlan, dbDetail.layer, dbDetail.questType);
|
||
let { rewards } = dbDetail;
|
||
if (replaceReward && replaceReward.rewards.length > 0) {
|
||
let newRewards = [...rewards.filter(reward => reward.rewardType != rewardType), ...replaceReward.rewards.filter(reward => reward.rewardType == rewardType)].map(reward => ({ ...reward, reRandRewardCnt: 1 })).sort((a, b) => a.groupIndex - b.groupIndex);
|
||
dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards: newRewards } });
|
||
}
|
||
|
||
return resResult(STATUS.SUCCESS, { rewards: dbDetail.rewards });
|
||
}
|
||
|
||
/**
|
||
* 选择奖励
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async chooseReward(msg: { gameCode: string, detailCode: string, groupIndex: number, optionIndexs: number[] }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let sid = session.get('sid');
|
||
|
||
const { gameCode, detailCode, groupIndex, optionIndexs } = msg;
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
let { status, rewards, layer, nodeType, warId = 0, challenge } = dbDetail;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
// 检测有关卡的是否挑战成功
|
||
if (warId != 0 && status != 1) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
if (!rewards || rewards.length == 0) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
let { rewardType, options, groupStatus, chooseNum } = rewards.find((obj) => obj.groupIndex == groupIndex);
|
||
|
||
// if (groupStatus == ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
let handleAddFun = new HandleAddCard(session, gameCode, dbDetail);
|
||
let incCoin = 0, redCoin = 0;
|
||
// //处理下试炼币
|
||
// if (rewardType == 0) {
|
||
// incCoin = chooseNum;
|
||
// groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE;
|
||
// const result = await RougelikeRecordDetailModel.findOneAndUpdate({ gameCode, detailCode, 'rewards.groupIndex': groupIndex }, { 'rewards.$.groupStatus': groupStatus, }, { new: true, upsert: true }).lean(true);
|
||
// if (result.rewards.find((obj) => obj.groupStatus != ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) == undefined) {
|
||
// await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } })
|
||
// }
|
||
// await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: incCoin, coinTotal: incCoin } })
|
||
// return resResult(STATUS.SUCCESS, { addCharas: await updateMaxHp(roleId, gameCode, dbRecord.type, dbRecord.grade), addCards: [], incCoin, redCoin });
|
||
// }
|
||
|
||
|
||
// 特性卡可以选多次
|
||
let passiveChooseCount = 0;
|
||
if (rewardType == ROUGE_LIKE_CARD_TYPE.PASSIVE || rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) {
|
||
passiveChooseCount = options.reduce((accumulator, obj) => {
|
||
if (obj.optionStatus === ROUGE_LIKE_CHOOSE_REWARD.CHOOSE) return accumulator + 1;
|
||
return accumulator;
|
||
}, 0);
|
||
if (chooseNum - passiveChooseCount < optionIndexs.length) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
}
|
||
|
||
if (optionIndexs.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
let tempOptions: RewardOption[] = options.filter(opt => optionIndexs.includes(opt.optionIndex));
|
||
if (tempOptions.length > chooseNum) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
|
||
for (let { rewardId, passiveCardIds, optionStatus, optionIndex } of tempOptions) {
|
||
if (optionStatus != 0) return resResult(STATUS.REWARD_NO_CHOOSE);
|
||
let cardCode = genCode(8);
|
||
if (rewardType == ROUGE_LIKE_CARD_TYPE.CHARA) {
|
||
// 更新角色卡
|
||
handleAddFun.pushChara(rewardId, await getMaxHp(roleId, gameCode, rewardId, dbRecord.type, dbRecord.grade), passiveCardIds || []);
|
||
//休整点 消耗
|
||
if (nodeType == ROUGE_LIKE_NODE_TYPE.REST_POINT) {
|
||
let charaData = gameData.rougeChara.get(rewardId);
|
||
if (!charaData) return;
|
||
redCoin += charaData.recruitConsume || 0;
|
||
}
|
||
} else {
|
||
// 更新特性卡or圣物
|
||
handleAddFun.pushCard(rewardId, rewardType);
|
||
}
|
||
optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE;
|
||
options.forEach((ele) => { if (ele.optionIndex == optionIndex) ele.optionStatus = optionStatus; });
|
||
}
|
||
|
||
if ((dbRecord.coin || 0) < redCoin) return resResult(STATUS.COIN_NOT_ENOUGH);
|
||
if (redCoin > 0) await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -redCoin } });
|
||
|
||
groupStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE;
|
||
|
||
if (nodeType == ROUGE_LIKE_NODE_TYPE.CHALLENGE) {
|
||
// 挑战关领奖更新
|
||
await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } })
|
||
} else {
|
||
// 更新进度
|
||
await updateChalleng(dbRecord, roleId, sid, gameCode, layer, []); // 更新挑战进度
|
||
}
|
||
|
||
await RougelikeRecordDetailModel.updateRewardByGroupIndex(gameCode, detailCode, groupIndex, groupStatus, options);
|
||
|
||
let addResult = await handleAddFun.save();
|
||
addResult = await handleAddFun.getHolyEffect();
|
||
|
||
return resResult(STATUS.SUCCESS, { ...addResult, incCoin, redCoin });
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* 商店购买
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async shopBuy(msg: { gameCode: string, detailCode: string, optionIndex: number }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let sid = session.get('sid');
|
||
|
||
let { gameCode, detailCode, optionIndex } = msg;
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.SHOP_NO_BUY);
|
||
|
||
let { status = 0, shops, layer, nodeType } = dbDetail;
|
||
if (status == 1 || !shops || shops.length == 0) return resResult(STATUS.SHOP_NO_BUY);
|
||
|
||
let shop = shops.find((obj) => obj.optionIndex == optionIndex);
|
||
if (!shop || shop.optionStatus != ROUGE_LIKE_CHOOSE_REWARD.NOCHOOSE) return resResult(STATUS.SHOP_NO_BUY);
|
||
|
||
let dbRecord = await RougelikeRecordModel.findByGameCode(gameCode);
|
||
if (!dbRecord || (dbRecord.coin || 0) < shop.price) return resResult(STATUS.COIN_NOT_ENOUGH);
|
||
|
||
|
||
shop.optionStatus = ROUGE_LIKE_CHOOSE_REWARD.CHOOSE;
|
||
|
||
await RougelikeRecordDetailModel.updateShopByCode(gameCode, detailCode, optionIndex, shop.optionStatus);
|
||
await RougelikeRecordModel.updateByGameCode(gameCode, { $set: { coin: (dbRecord.coin || 0) - shop.price } });
|
||
|
||
let handleAddFun = new HandleAddCard(session, gameCode, dbDetail);
|
||
handleAddFun.pushCard(shop.rewardId, shop.rewardType);
|
||
let result = await handleAddFun.save();
|
||
result = await handleAddFun.getHolyEffect();
|
||
|
||
return resResult(STATUS.SUCCESS, { curShop: shop, ...result, redCoin: -shop.price });
|
||
|
||
}
|
||
|
||
/**
|
||
* 结束这一节点
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async nodeEnd(msg: { gameCode: string, detailCode: string }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
const { gameCode, detailCode } = msg;
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.NO_EXIT_NODE);
|
||
let { layer, nodeType, status = 0, shops, warId = 0 } = dbDetail;
|
||
if ((warId != 0 && status != 1)) {
|
||
//检测关卡是否挑战成功
|
||
return resResult(STATUS.NODE_NO_END)
|
||
}
|
||
status = 1;
|
||
await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { status } });
|
||
if (nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE) {
|
||
await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } });
|
||
}
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, detailCode, status, ...await getGame(roleId) })
|
||
}
|
||
|
||
|
||
/**
|
||
* 问号点选择题
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async chooseOption(msg: { gameCode: string, detailCode: string, eventOptions: number[] }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
let sid = session.get('sid');
|
||
let serverId = session.get('serverId');
|
||
|
||
const { gameCode, detailCode, eventOptions } = msg;
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
let { layer, nodeType, status = 0, question = {} as Quest } = dbDetail;
|
||
if (status == 1) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
|
||
let checkAfterGroup = 0, optionGroupIds: number[] = [];
|
||
let handleAddFun = new HandleAddCard(session, gameCode, dbDetail);
|
||
for (let [index, id] of eventOptions.entries()) {
|
||
const rougeEventOptionData = gameData.rougeEventOption.get(id);
|
||
if (!rougeEventOptionData) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
const { randomEventId, optionGroup, afterGroup, holyCardPlan } = rougeEventOptionData;
|
||
|
||
if (randomEventId != (question.randomEventId || 0)) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
|
||
if (index != 0 && checkAfterGroup != optionGroup) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
if (!optionGroupIds.includes(optionGroup)) optionGroupIds.push(optionGroup);
|
||
|
||
if (!question.EventOptions) question.EventOptions = [];
|
||
question.EventOptions.push(id);
|
||
checkAfterGroup = afterGroup;
|
||
|
||
const rougeHolyCardPlanData = gameData.rougeHolyCardPlan.get(holyCardPlan);
|
||
if (!rougeHolyCardPlanData || rougeHolyCardPlanData.length == 0) continue;
|
||
let newCards = [];
|
||
let cardsMap = await getCardCount(gameCode, ROUGE_LIKE_CARD_TYPE.HOLY);
|
||
for (let obj of rougeHolyCardPlanData) {
|
||
let holyCardData = gameData.rougeHolyCard.get(obj.cardId);
|
||
if (!holyCardData) continue;
|
||
const getLimit = cardsMap.get(obj.cardId) || 0;
|
||
if (getLimit >= (holyCardData?.getLimit || 0)) continue; //处理限制获取数量
|
||
newCards.push(obj);
|
||
}
|
||
let cardId = 0;
|
||
if (newCards.length > 0) {
|
||
cardId = getRandEelmWithWeight(newCards).dic.cardId;
|
||
}
|
||
|
||
handleAddFun.pushHolyCard(cardId);
|
||
}
|
||
|
||
status = 1;
|
||
|
||
await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { question, status } })
|
||
await RougelikeLayerModel.updateByGameCode(gameCode, layer, { $set: { hasPass: true } })
|
||
|
||
let result = await handleAddFun.save();
|
||
result = await handleAddFun.getHolyEffect();
|
||
|
||
await addSameTypeCollect(roleId, sid, gameCode, COLLECTION_TYPE.EVENT, optionGroupIds);
|
||
//任务
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_EVENT_COLLECT, { eventGroups: optionGroupIds });
|
||
|
||
return resResult(STATUS.SUCCESS, { ...result })
|
||
}
|
||
|
||
|
||
/**
|
||
* 休整点恢复
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async recovery(msg: { gameCode: string, detailCode: string }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
|
||
const { gameCode, detailCode } = msg;
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
let { restPoints = [], nodeType, status, rewards } = dbDetail;
|
||
if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
|
||
let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.RECOVERY) || new RestPoint();
|
||
if (restPoint.recoveryCnt && restPoint.recoveryCnt > 0) return resResult(STATUS.NO_TIME_RECOVERY);
|
||
restPoint.recoveryCnt = 1;
|
||
restPoint.restType = REST_POINT_TYPE.RECOVERY;
|
||
restPoint.recoveryCharas = [];
|
||
let dbCharas = await RougelikeCharaModel.findByGameCode(gameCode);
|
||
let updateCharas: RougelikeCharaPara[] = [];
|
||
|
||
let hpRatio = await getRecoveryExtendHp(roleId, gameCode);
|
||
for (let { gameCode, charaCode, charaId, cards, hp = 0, maxHp = 0, ap, shield, roundSkill, apSkill } of dbCharas) {
|
||
if (hp == 0) continue;
|
||
let beforeHp = hp;
|
||
hp = Math.floor(Math.min(hp + maxHp * ROUGELIKE.RECOVERY_RATIO / 100 + maxHp * hpRatio / 100, maxHp));
|
||
updateCharas.push({ gameCode, charaCode, hp });
|
||
restPoint.recoveryCharas.push({ charaCode, charaId, beforeHp, afterHp: hp });
|
||
}
|
||
restPoints.push({ restType: restPoint.restType, recoveryCnt: restPoint.recoveryCnt, recoveryCharas: restPoint.recoveryCharas });
|
||
|
||
await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } });
|
||
await RougelikeCharaModel.bulkWriteUpdate(updateCharas);
|
||
|
||
const charas: CommonChara[] = formateCharasOrCards(dbCharas, ROUGE_LIKE_CARD_TYPE.CHARA)?.charas || [];
|
||
|
||
return resResult(STATUS.SUCCESS, { restPoints, charas, reward: { rewards } })
|
||
}
|
||
|
||
/**
|
||
* 休整点强化
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async trainCard(msg: { gameCode: string, detailCode: string, cardCode: string }, session: BackendSession) {
|
||
let roleId = session.get('roleId');
|
||
|
||
const { gameCode, detailCode, cardCode } = msg;
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode)
|
||
if (!dbRecord) return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
if (dbRecord.status != ROUGE_LIKE_STATUS.INPROGRESS) return resResult(STATUS.ROUGELIKE_GAME_END);
|
||
|
||
let dbDetail = await RougelikeRecordDetailModel.findByCode(gameCode, detailCode);
|
||
if (!dbDetail) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
let { layer, nodeType, status = 0, question, restPoints = [], rewards } = dbDetail;
|
||
if (status == 1 || nodeType != ROUGE_LIKE_NODE_TYPE.REST_POINT) return resResult(STATUS.NODE_NO_CHOOSE);
|
||
|
||
let dbCard = await RougelikeCardModel.findByCode(gameCode, cardCode);
|
||
if (!dbCard) return resResult(STATUS.NO_CARD);
|
||
let { type, cardId, charaId = 0, lv = 0 } = dbCard;
|
||
|
||
const passiveCardData = gameData.rougePassiveCard.get(cardId);
|
||
if (!passiveCardData) return resResult(STATUS.NO_CARD);
|
||
const passiveCardByGroupData = gameData.rougePassiveCardByGroup.get(passiveCardData.group || 0);
|
||
if (passiveCardByGroupData.length == 0 || passiveCardByGroupData.length == 1) return resResult(STATUS.HIGH_LV);
|
||
let passiveCardDataMap = passiveCardByGroupData.reduce((result, cur) => { result.set(cur.lv, cur); return result; }, new Map<number, DicRougePassiveCard>());
|
||
if (!passiveCardDataMap.has(lv + 1)) return resResult(STATUS.HIGH_LV);
|
||
|
||
const strengthConsume = passiveCardData.strengthConsume || 0;
|
||
const { lv: cardLv, id } = passiveCardDataMap.get(lv + 1);
|
||
if (lv == cardLv) return resResult(STATUS.HIGH_LV);
|
||
|
||
let realConsume = Math.floor(strengthConsume * await getTrainCardDiscount(roleId, gameCode) / 100);
|
||
if ((dbRecord.coin || 0) < realConsume) return (STATUS.COIN_NOT_ENOUGH);
|
||
|
||
let restPoint = restPoints.find(cur => cur.restType == REST_POINT_TYPE.TRAIN) || new RestPoint();
|
||
restPoint.restType = REST_POINT_TYPE.TRAIN;
|
||
if (!restPoint.trainCardCnt) restPoint.trainCardCnt = 0;
|
||
restPoint.trainCardCnt += 1;
|
||
if (!restPoint.trainCards) restPoint.trainCards = [];
|
||
restPoint.trainCards.push({ cardCode, cardId: id, beforeLv: lv, afterLv: lv + 1 });
|
||
|
||
if (restPoints.find(cur => cur.restType == restPoint.restType) == undefined) {
|
||
restPoints.push({ restType: restPoint.restType, trainCardCnt: restPoint.trainCardCnt, trainCards: restPoint.trainCards })
|
||
}
|
||
else restPoints.forEach(obj => {
|
||
if (obj.restType == restPoint.restType) {
|
||
obj.trainCardCnt = restPoint.trainCardCnt;
|
||
obj.trainCards = restPoint.trainCards;
|
||
}
|
||
|
||
})
|
||
await RougelikeRecordModel.updateByGameCode(gameCode, { $inc: { coin: -realConsume } });
|
||
await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { restPoints } });
|
||
const newDbCard = await RougelikeCardModel.updateByCode(gameCode, cardCode, { $set: { cardId: id }, $inc: { lv: 1 } });
|
||
const cards: CommonCard[] = formateCharasOrCards([newDbCard], ROUGE_LIKE_CARD_TYPE.PASSIVE)?.cards || [];
|
||
|
||
if (charaId > 0) {
|
||
const dbCharas = await RougelikeCharaModel.findByGameCodeAndCharaId(gameCode, charaId);
|
||
let isEnd = false;
|
||
for (let { cards = [], charaCode } of dbCharas) {
|
||
for (let obj of cards) {
|
||
if (cardCode != obj.cardCode) continue;
|
||
obj.cardId = id;
|
||
await RougelikeCharaModel.findOneAndUpdate({ gameCode, charaCode, 'cards.cardCode': cardCode }, { 'cards.$.cardId': id }, { new: true, upsert: true }).lean(true);
|
||
isEnd = true;
|
||
break;
|
||
}
|
||
if (isEnd) break;
|
||
}
|
||
}
|
||
|
||
return resResult(STATUS.SUCCESS, { restPoints, cards, reward: { rewards }, redCoin: -realConsume, })
|
||
|
||
}
|
||
|
||
/**
|
||
* 选择一张技能卡
|
||
* @param msg
|
||
* @returns
|
||
*/
|
||
async chooseSkillCard(msg: { gameCode: string, charaCode: string, skillType: number, id: number }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
let sid: string = session.get('sid');
|
||
let serverId: number = session.get('serverId');
|
||
|
||
const { gameCode, charaCode, skillType, id } = msg;
|
||
|
||
let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode);
|
||
if (!dbChara) return resResult(STATUS.NO_CARD);
|
||
|
||
if (id > 0) {
|
||
const dicSkillCard = gameData.rougeSkillCard.get(id);
|
||
if (!dicSkillCard) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
if (dicSkillCard.skillType != skillType) return resResult(STATUS.WRONG_PARMS);
|
||
|
||
// 检查数量
|
||
if (!await checkCanChooseSkillCard(roleId, gameCode, id, dbChara.cards))
|
||
return resResult(STATUS.ROUGE_PASSIVE_CARD_NOT_ENOUGH);
|
||
}
|
||
|
||
let chara = await RougelikeCharaModel.putOnOrOffSkillCard(gameCode, charaCode, skillType, id);
|
||
if (!dbChara) return resResult(STATUS.NO_CARD);
|
||
// 更新图鉴
|
||
await addSingleCollect(roleId, sid, gameCode, COLLECTION_TYPE.SKILL_CARD, id);
|
||
|
||
// 任务
|
||
let dicSkillCard = gameData.rougeSkillCard.get(id);
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_AUTHOR_CARD_COLLECT, { authorType: dicSkillCard.authorType, cardType: TASK_ROUGE_CARD_TYPE.SKILL, cardIds: [id] });
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
curChara: new CommonChara(chara)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 安装或者卸下特性卡
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async putOnOrOffCard(msg: { gameCode: string, charaCode: string, cards: SlotCard[] }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
let { gameCode, charaCode, cards } = msg;
|
||
|
||
// 获取角色卡db数据
|
||
let dbChara = await RougelikeCharaModel.findByCode(gameCode, charaCode);
|
||
if (!dbChara) return resResult(STATUS.NO_CARD);
|
||
if (!dbChara.cards || dbChara.cards.length == 0) return resResult(STATUS.SLOT_UNLOCK);
|
||
let dbCharaCardsMap = dbChara.cards.reduce((result, cur) => { result.set(cur.index, cur); return result; }, new Map<number, Card>());
|
||
|
||
// 获取需要安装、卸下的特性卡db数据
|
||
let cardCodes: string[] = [];
|
||
cards.forEach((ele) => { cardCodes.push(ele.cardCode); });
|
||
dbChara.cards.forEach((ele) => { cardCodes.push(ele.cardCode); })
|
||
let dbCards: RougelikeCardType[] = await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes);
|
||
if (dbCards.length == 0) return resResult(STATUS.NO_CARD);
|
||
let dbCardsMap = dbCards.reduce((result, cur) => { result.set(cur.cardCode, cur); return result; }, new Map<string, RougelikeCardType>());
|
||
|
||
let newCardsMap = new Map<string, RougelikeCardType>();
|
||
for (let { index, cardCode } of cards) {
|
||
// 检测卡槽解锁
|
||
let slot = dbCharaCardsMap.get(index)
|
||
if (!slot) return resResult(STATUS.SLOT_UNLOCK);
|
||
|
||
//处理旧的cardCode
|
||
let oldSotCardCode = clone(slot.cardCode);
|
||
let updateObj = dbCardsMap.get(oldSotCardCode);
|
||
if (updateObj) {
|
||
updateObj.charaId = 0;
|
||
dbCardsMap.set(oldSotCardCode, updateObj);
|
||
newCardsMap.set(oldSotCardCode, updateObj);
|
||
}
|
||
|
||
//处理新的cardCode安装
|
||
let update = dbCardsMap.get(cardCode);
|
||
dbCharaCardsMap.set(index, { index, cardCode: cardCode, cardId: update?.cardId || 0 });
|
||
if (update) {
|
||
if (update.type != ROUGE_LIKE_CARD_TYPE.PASSIVE) return resResult(STATUS.NO_PASSIVE);
|
||
update.charaId = dbChara.charaId;
|
||
dbCardsMap.set(cardCode, update);
|
||
newCardsMap.set(cardCode, update);
|
||
}
|
||
}
|
||
let newCards = Array.from(dbCharaCardsMap.values());
|
||
let tempCards = new Map<number, number>();
|
||
for (let { cardId } of newCards) {
|
||
if (!cardId) continue;
|
||
if (tempCards.has(cardId)) return resResult(STATUS.ROUGE_NO_CAN_PUT_SAME_ID);
|
||
tempCards.set(cardId, cardId);
|
||
}
|
||
|
||
// 如果卸下之后技能卡需要的被动卡不够,需要把技能卡卸下
|
||
let { apSkill, roundSkill } = dbChara;
|
||
if (apSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, apSkill, newCards)) apSkill = 0;
|
||
if (roundSkill > 0 && !await checkCanChooseSkillCard(roleId, gameCode, roundSkill, newCards)) roundSkill = 0;
|
||
|
||
//更新角色卡db, 特性卡db
|
||
let newChara = await RougelikeCharaModel.updateByCode(gameCode, charaCode, { $set: { cards: newCards, apSkill, roundSkill } });
|
||
await RougelikeCardModel.bulkWriteUpdate(Array.from(newCardsMap.values()).map(obj => ({ gameCode, cardCode: obj.cardCode, charaId: obj.charaId })))
|
||
let curCards = Array.from(dbCardsMap.values()).map(obj => ({ cardCode: obj.cardCode, type: obj.type, charaId: obj.charaId, lv: obj.lv }));
|
||
|
||
return resResult(STATUS.SUCCESS, { curCards, curChara: new CommonChara(newChara) })
|
||
}
|
||
|
||
|
||
async exchangeChara(msg: { gameCode: string, oldCharaCode: string, newCharaCode: string }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
const { gameCode, oldCharaCode, newCharaCode } = msg;
|
||
const result = await RougelikeCharaModel.findByCodes(gameCode, [oldCharaCode, newCharaCode]);
|
||
if (result.length != 2) return (STATUS.NO_CARD);
|
||
let oldChara = {} as RougelikeCharaType, newChara = {} as RougelikeCharaType;
|
||
for (let val of result) {
|
||
if (val.charaCode == oldCharaCode) oldChara = val;
|
||
if (val.charaCode == newCharaCode) newChara = val;
|
||
}
|
||
|
||
let temp = clone(newChara.seqId);
|
||
newChara.seqId = clone(oldChara.seqId);
|
||
oldChara.seqId = temp;
|
||
// 更新角色卡
|
||
await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]);
|
||
let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas;
|
||
|
||
|
||
// // 处理新卡
|
||
// let { charaCode, charaId, maxHp, seqId } = newChara;
|
||
// newChara = clone(oldChara);
|
||
// newChara.charaCode = charaCode;
|
||
// newChara.charaId = charaId;
|
||
// newChara.maxHp = maxHp;
|
||
|
||
// let cardCodes = [];
|
||
// let updateArr: RougelikeCardPara[] = [];
|
||
// for (let val of newChara.cards) {
|
||
// cardCodes.push(val.cardCode);
|
||
// updateArr.push({ gameCode, cardCode: val.cardCode, charaId });
|
||
// }
|
||
|
||
// // 处理旧卡
|
||
// oldChara.cards.forEach((cur) => { cur.cardCode = '', cur.cardId = 0 });
|
||
// oldChara.ap = oldChara.apSkill = oldChara.roundSkill = 0;
|
||
// oldChara.seqId = seqId;
|
||
|
||
// // 更新角色卡
|
||
// await RougelikeCharaModel.bulkWriteUpdate([oldChara, newChara]);
|
||
|
||
// let cards = formateCharasOrCards(await RougelikeCardModel.findByGameCodeAndCardCodes(gameCode, cardCodes), ROUGE_LIKE_CARD_TYPE.PASSIVE).cards;
|
||
// // 更新card
|
||
// await RougelikeCardModel.bulkWriteUpdate(updateArr);
|
||
|
||
// let charas = formateCharasOrCards([oldChara, newChara], ROUGE_LIKE_CARD_TYPE.CHARA).charas;
|
||
|
||
return resResult(STATUS.SUCCESS, { charas });
|
||
}
|
||
|
||
/**
|
||
* 解锁科技点
|
||
* @param msg
|
||
* @param session
|
||
*/
|
||
async unlockTech(msg: { techId: number }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
let sid: string = session.get('sid');
|
||
let serverId: number = session.get('serverId');
|
||
|
||
const { techId } = msg;
|
||
|
||
let dicTech = gameData.rougeTech.get(techId);
|
||
if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
let techRecord = await RougelikeTechModel.findByRoleId(roleId);
|
||
let { unlockedTech = [] } = techRecord || {};
|
||
if (unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_TECH_HAS_UNLOCKED);
|
||
if (!checkPreRougeTech(techId, unlockedTech)) return resResult(STATUS.ROUGE_TECH_PRE_NOT_UNLOCKED);
|
||
|
||
// 检查消耗
|
||
let costResult = await handleCost(roleId, sid, dicTech.cost, ITEM_CHANGE_REASON.ROUGE_UNLOCK_TECH);
|
||
if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
|
||
let circleIds = gameData.rougeCircleByTech.get(techId) || [];
|
||
techRecord = await RougelikeTechModel.unlockTech(roleId, techId, circleIds);
|
||
if (!techRecord) return resResult(STATUS.ROUGE_TECH_SCORE_NOT_ENOUGH);
|
||
await updateEffectId(techRecord);
|
||
|
||
let resultData = getCurTechData(techRecord, techId);
|
||
//任务
|
||
await checkTask(serverId, roleId, sid, TASK_TYPE.ROUGE_TECH_OPEN, { count: 1 });
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
...resultData
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 放置法阵
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async putOnCircle(msg: { circleId: number, hid: number }, session: BackendSession) {
|
||
|
||
let roleId: string = session.get('roleId');
|
||
const { circleId, hid } = msg;
|
||
|
||
let techId = gameData.rougeTechCircle.get(circleId);
|
||
if (!techId) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
let dicTech = gameData.rougeTech.get(techId);
|
||
if (!dicTech) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
let techRecord = await RougelikeTechModel.findByRoleId(roleId);
|
||
if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK);
|
||
let { unlockedTech = [] } = techRecord;
|
||
if (!unlockedTech.includes(techId)) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK);
|
||
|
||
let ce = 0;
|
||
if (hid != 0) {
|
||
let hero = await HeroModel.findByHidAndRole(hid, roleId, 'ce');
|
||
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
|
||
ce = hero.ce || 0;
|
||
}
|
||
|
||
techRecord = await RougelikeTechModel.putOnCircle(roleId, circleId, hid, ce);
|
||
if (!techRecord) return resResult(STATUS.ROUGE_CIRCLE_NOT_UNLOCK);
|
||
await updateEffectId(techRecord);
|
||
|
||
let resultData = getCurTechData(techRecord, techId);
|
||
return resResult(STATUS.SUCCESS, {
|
||
...resultData
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 领取图鉴奖励
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async receiveCollectionReward(msg: { type: number, id: number }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
let roleName: string = session.get('roleName');
|
||
let sid: string = session.get('sid');
|
||
let { type, id } = msg;
|
||
|
||
let dic: DicRougePassiveCollect | DicRougeHolyCard | DicRougeSkillCard | DicRougeOptionGroup;
|
||
let num = 1;
|
||
if (type == COLLECTION_TYPE.PASSIVE_CARD_SUM) {
|
||
dic = gameData.rougePassiceCollect.get(id);
|
||
num = dic?.num || 0;
|
||
} else if (type == COLLECTION_TYPE.HOLY_CARD) {
|
||
dic = gameData.rougeHolyCard.get(id);
|
||
} else if (type == COLLECTION_TYPE.SKILL_CARD) {
|
||
dic = gameData.rougeSkillCard.get(id);
|
||
} else if (type == COLLECTION_TYPE.EVENT) {
|
||
dic = gameData.rougeOptionGroup.get(id);
|
||
}
|
||
if (!dic) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
let collect = await RougelikeCollectionModel.findByRoleAndId(roleId, type, id);
|
||
if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH);
|
||
if (collect.received.includes(id)) return resResult(STATUS.ROUGE_COLLECT_HAS_RECEIVED);
|
||
|
||
collect = await RougelikeCollectionModel.receive(roleId, type, id, num);
|
||
if (!collect) return resResult(STATUS.ROUGE_COLLECT_NOT_ENOUGH);
|
||
let goods = await addItems(roleId, roleName, sid, dic.collectReward, ITEM_CHANGE_REASON.RECEIVE_COLLECT_REWARD);
|
||
|
||
return resResult(STATUS.SUCCESS, {
|
||
goods, curCollection: new CollectionReturnParam(collect)
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 领取积分奖励
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async receiveScore(msg: { index: number }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
let sid: string = session.get('sid');
|
||
let roleName: string = session.get('roleName');
|
||
let { index } = msg;
|
||
const lastMaxLv = await RougelikeExtendModel.getLastMaxLv(roleId);
|
||
const rougeScoreRewardByLvData = gameData.rougeScoreRewardByLv.get(lastMaxLv);
|
||
if (!rougeScoreRewardByLvData) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
let dicScore = rougeScoreRewardByLvData.get(index);
|
||
if (!dicScore) return resResult(STATUS.DIC_DATA_NOT_FOUND);
|
||
|
||
let scoreData = await RougelikeScoreModel.findByRoleId(roleId);
|
||
if (!scoreData || scoreData.score < dicScore.score) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH);
|
||
if (scoreData.received.includes(index)) return resResult(STATUS.ROUGE_SCORE_HAS_RECEIVED);
|
||
|
||
scoreData = await RougelikeScoreModel.receive(roleId, dicScore.score, index);
|
||
if (!scoreData) return resResult(STATUS.ROUGE_SCORE_NOT_ENOUGH);
|
||
|
||
let goods = await addItems(roleId, roleName, sid, dicScore.reward, ITEM_CHANGE_REASON.RECEIVE_ROUGE_SCORE_REWARD);
|
||
return resResult(STATUS.SUCCESS, {
|
||
receivedScore: scoreData.received,
|
||
goods
|
||
});
|
||
}
|
||
|
||
async challengeRandom(msg: { detailCode: string }, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
const { detailCode } = msg;
|
||
let dbDetail = await RougelikeRecordDetailModel.findByDetailCode(detailCode);
|
||
if (!dbDetail) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
let { gameCode, layer, nodeId, nodeType, rewards = [], challenge } = dbDetail;
|
||
if (rewards.length > 0 || nodeType != ROUGE_LIKE_NODE_TYPE.CHALLENGE || (challenge?.status || 0) < 2) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
|
||
const dbRecord = await RougelikeRecordModel.findByGameCode(gameCode);
|
||
if (!dbRecord) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
const { authorType, type, grade } = dbRecord;
|
||
|
||
const typeGradeData = gameData.rougeTypeGrade.get(type + '_' + grade);
|
||
if (!typeGradeData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
const layerPlanData = gameData.rougeLayerPlan.get(typeGradeData.layerPlan + '_' + layer);
|
||
if (!layerPlanData) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
let result = await getLayerNodeReward(roleId, gameCode, authorType, nodeId, layerPlanData.rewardPlan, layer);
|
||
if (!result || !result.rewards) return resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
rewards = result.rewards;
|
||
|
||
dbDetail = await RougelikeRecordDetailModel.updateByCode(gameCode, detailCode, { $set: { rewards } });
|
||
if (!dbDetail || !dbDetail.rewards) resResult(STATUS.ROUGE_CHALLENGE_RANDOM_FAIL);
|
||
|
||
return resResult(STATUS.SUCCESS, { gameCode, detailCode, reward: { rewards: dbDetail.rewards } })
|
||
}
|
||
|
||
/**
|
||
* debug接口,清空科技树
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async debugClearTech(msg: {}, session: BackendSession) {
|
||
let roleId: string = session.get('roleId');
|
||
await RougelikeTechModel.clearTech(roleId);
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
|
||
async debugAddCard(msg: { type: number, id: number }, session: BackendSession) {
|
||
let { type, id } = msg;
|
||
|
||
let roleId: string = session.get('roleId');
|
||
let sid: string = session.get('sid');
|
||
const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS);
|
||
if (!dbRecord) {
|
||
return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
}
|
||
|
||
let handleAddFun = new HandleAddCard(session, dbRecord.gameCode);
|
||
if (type == ROUGE_LIKE_CARD_TYPE.CHARA) {
|
||
handleAddFun.pushChara(id, await getMaxHp(roleId, dbRecord?.gameCode || '', id, dbRecord.type, dbRecord.grade), []);
|
||
} else if (type == ROUGE_LIKE_CARD_TYPE.HOLY) {
|
||
handleAddFun.pushHolyCard(id);
|
||
} else if (type == ROUGE_LIKE_CARD_TYPE.PASSIVE) {
|
||
handleAddFun.pushPassiveCard(id);
|
||
} else {
|
||
return resResult(STATUS.WRONG_PARMS);
|
||
}
|
||
let result = await handleAddFun.save();
|
||
result = await handleAddFun.getHolyEffect();
|
||
return resResult(STATUS.SUCCESS, result);
|
||
}
|
||
|
||
// debug接口
|
||
async debugAddCollection(msg: { type: number, id: number }, session: BackendSession) {
|
||
let { type, id } = msg;
|
||
let roleId: string = session.get('roleId');
|
||
let sid: string = session.get('sid');
|
||
const dbRecord = await RougelikeRecordModel.findByRoleIdAndStatus(roleId, ROUGE_LIKE_STATUS.SUCCESS);
|
||
if (!dbRecord) {
|
||
return resResult(STATUS.NO_ROUGELIKE_GAME);
|
||
}
|
||
await addSingleCollect(roleId, sid, dbRecord.gameCode, type, id);
|
||
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
|
||
async debugAddScore(msg: { score: number }, session: BackendSession) {
|
||
let { score } = msg;
|
||
let roleId: string = session.get('roleId');
|
||
let result = await RougelikeScoreModel.incScore(roleId, score);
|
||
return resResult(STATUS.SUCCESS, { weeklyScore: result.score })
|
||
}
|
||
|
||
async debugRepaireScoreReward() {
|
||
await repaireSendScoreReward();
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
/**
|
||
* debug添加试炼通关
|
||
* @param msg
|
||
* @param session
|
||
* @returns
|
||
*/
|
||
async debugAddLimitId(msg: { id: number }, session: BackendSession) {
|
||
const { id } = msg;
|
||
const roleId: string = session.get('roleId');
|
||
const typeGradeByIdData = gameData.rougeTypeGradeById.get(id);
|
||
if (typeGradeByIdData) {
|
||
// for (let i = 3; i <= 42; i++) {
|
||
await RougelikeExtendModel.update(roleId, id, [], genCode(8));
|
||
|
||
// }
|
||
}
|
||
return resResult(STATUS.SUCCESS);
|
||
}
|
||
} |