import { Application, BackendSession, HandlerService, } from "pinus"; import { STATUS, EQUIP_STRENGTHEN_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, HERO_SYSTEM_TYPE, CONSUME_TYPE, HERO_GROW_MAX, MSG_SOURCE, JEWEL_PUSH_LV, TASK_TYPE, HERO_CE_RATIO } from "../../../consts"; import { ItemInter } from "../../../pubUtils/interface"; import { resResult, parseGoodStr } from "../../../pubUtils/util"; import { addItems, handleCost, decreaseItems, combineItems, CheckMeterial } from "../../../services/rewardService"; import { EquipModel, EquipType } from "../../../db/Equip"; import { HeroModel, EPlace, HeroType } from "../../../db/Hero"; import Role from "../../../db/Role"; import { calPlayerCeAndSave } from "../../../services/playerCeService"; import { getGoodById, gameData } from "../../../pubUtils/data"; import { BAG, EQUIP } from "../../../pubUtils/dicParam"; import { ITID, QUALITY_TYPE, equipTypeToSortAttr, IT_TYPE, QUENCH_TYPE, REFINE_TYPE } from "../../../consts"; import { checkMaterialEnough, checkEquipCanPut, quenchOnce, checkQuenchMaxByQualityAndGrade, getRandSeResult, refineOnce, checkRefineReachNextLv, calEquipCe } from "../../../services/equipService"; import { findIndex, pick } from 'underscore'; import { pushEquipRefineSucMsg, pushNormalEquipMsg, pushNormalItemMsg } from "../../../services/chatService"; import { checkTaskWithHero, checkTaskWithEquip, checkTask, checkTaskWithArgs, checkTaskConditionEquipSuitJewelStage, checkActivityTask } from "../../../services/taskService"; import { QuenchLogParam } from "../../../domain/roleField/equip"; import { calEquipSeids } from "../../../pubUtils/playerCe"; export default function (app: Application) { new HandlerService(app, {}); return new EquipHandler(app); } export class EquipHandler { constructor(private app: Application) { } // test接口添加任意道具 public async addItem(msg: { id: number, count: number }, session: BackendSession) { let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let { id, count } = msg; let goods = await addItems(roleId, roleName, sid, [{ id, count }]); return resResult(STATUS.SUCCESS, { goods }); } // 合成装备 public async composeEquip(msg: { gid: number, originalEquip: number[] }, session: BackendSession) { let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); const serverId: number = session.get('serverId'); // 消耗材料 // 获得装备 let { gid, originalEquip } = msg; let targetGood = gameData.goods.get(gid); if (!targetGood) return resResult(STATUS.DIC_DATA_NOT_FOUND); let cost: ItemInter[] = []; let jewels: ItemInter[] = []; // 需要返还的镶嵌在装备上的宝石 if (targetGood.suitId > 0) { // 套装 cost = cost.concat(targetGood.composeMaterial); let specialMaterial = targetGood.specialMaterial; let costCount = 0; let equips = await EquipModel.getEquips(roleId, originalEquip); for (let equip of equips) { let { id, seqId, holes } = equip; if (specialMaterial.ids.includes(id)) { costCount++; cost.push({ id, seqId, count: 1 }); for (let { jewel } of holes) { if (jewel > 0) jewels.push({ id: jewel, count: 1 }); } } } if (specialMaterial.count > costCount) { return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); } } else { // 普通装备 cost.push({ id: targetGood.pieceId, count: targetGood.pieces }); } let result = await handleCost(roleId, sid, cost); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); await addItems(roleId, roleName, sid, jewels); // 宝石返还 let items = [{ id: gid, count: 1 }]; let goods = await addItems(roleId, roleName, sid, items); if (targetGood.suitId) { pushNormalEquipMsg(roleId, roleName, serverId, MSG_SOURCE.EQUIP_COMPOSE_SUIT, gid, targetGood.name, targetGood.quality); } if (targetGood.quality >= QUALITY_TYPE.ORANGE) { pushNormalEquipMsg(roleId, roleName, serverId, MSG_SOURCE.EQUIP_COMPOSE_ORANGE, gid, targetGood.name, targetGood.quality); } return resResult(STATUS.SUCCESS, { goods }); } // 装备栏强化 public async strengthen(msg: { hid: number, ePlaceId: number, type: number }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); const serverId = session.get('serverId'); let sid: string = session.get('sid'); let { hid, ePlaceId, type } = msg; let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); if (!hero) return resResult(STATUS.HERO_NOT_FIND); let changeData = [];//变化的等级数据 let { ePlace, lv: playerLv } = hero; // 装备栏 let oldLvs = ePlace.map(cur => cur.lv); let strengthenArr = new Array(); if (type == EQUIP_STRENGTHEN_TYPE.SINGLE || type == EQUIP_STRENGTHEN_TYPE.SINGLE_QUICK) { // 单装备强化 strengthenArr = ePlace.filter(cur => cur.id == ePlaceId && cur.equip); } else if (type == EQUIP_STRENGTHEN_TYPE.ALL_QUICK) { // 全六件(装备中)的强化 strengthenArr = ePlace.filter(cur => cur.equip); } if (strengthenArr.length <= 0) { return resResult(STATUS.ROLE_EQUIP_PLACE_NOT_ENOUGH); } let minLv = strengthenArr[0].lv; // 从最低装备的等级开始 for (let { lv, id } of strengthenArr) { changeData.push({ hid: hid, id: id, oldLv: lv, lv: lv, }) if (lv < minLv) minLv = lv; } let { coin } = await Role.findByRoleId(roleId); let maxLv = type == EQUIP_STRENGTHEN_TYPE.SINGLE ? minLv + 1 : playerLv; if (maxLv > playerLv) maxLv = playerLv; if (minLv >= maxLv) { return resResult(STATUS.ROLE_EQUIP_REACH_MAX); } let costCoin = 0; // 消耗铜币 let flag = false; // 铜币不足 for (let i = minLv; i < maxLv; i++) { for (let s of strengthenArr) { if (s.lv == i) { let cost = gameData.strengthenCost.get(i + 1); if (!cost) { flag = true; break; } if (coin < costCoin + cost) { flag = true; break; } costCoin += cost; s.lv++; {//记录等级变化 let index = changeData.findIndex(obj => { return obj && obj.id == s.id }) if (index != -1) { changeData[index].lv = s.lv; } } } } if (flag) break; } if (costCoin <= 0) { // 连一级都不够升 return resResult(STATUS.ROLE_COIN_NOT_ENOUGH); } let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: costCoin }]); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); hero.ePlace = ePlace; await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); // 任务 await checkTaskWithHero(roleId, sid, TASK_TYPE.EQUIP_STRENGTHEN, hero, oldLvs); //成长任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_STRENGTHEN, 1, changeData) const curHero = { hid, ePlace: strengthenArr } return resResult(STATUS.SUCCESS, { curHero }); } // 装备栏一键强化至相应等级 public async strengthenAll(msg: { hid: number, lv: number }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); const serverId = session.get('serverId'); let changeData = [];//变化的等级数据 let { hid, lv: maxLv } = msg; // lv: 升到哪一级 let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); if (!hero) return resResult(STATUS.HERO_NOT_FIND); let { ePlace, lv: playerLv } = hero; // 装备栏 let oldLvs = ePlace.map(cur => cur.lv); let strengthenArr = ePlace.filter(cur => cur.equip); if (strengthenArr.length <= 0) { return resResult(STATUS.ROLE_EQUIP_PLACE_NOT_ENOUGH); } let minLv = strengthenArr[0].lv; // 从最低装备的等级开始 for (let { lv, id } of strengthenArr) { changeData.push({ hid: hid, id: id, oldLv: lv, lv: lv, }) if (lv < minLv) minLv = lv; } let { coin } = await Role.findByRoleId(roleId); if (maxLv > playerLv) { return resResult(STATUS.ROLE_EQUIP_REACH_MAX); } let costCoin = 0; // 消耗铜币 for (let i = minLv; i < maxLv; i++) { for (let s of strengthenArr) { if (s.lv == i) { let cost = gameData.strengthenCost.get(i + 1); costCoin += cost; s.lv++; {//记录等级变化 let index = changeData.findIndex(obj => { return obj && obj.id == s.id }) if (index != -1) { changeData[index].lv = s.lv; } } } } } if (costCoin > coin) { return resResult(STATUS.ROLE_COIN_NOT_ENOUGH); } let result = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN), count: costCoin }]); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); hero.ePlace = ePlace; await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); // 任务 await checkTaskWithHero(roleId, sid, TASK_TYPE.EQUIP_STRENGTHEN, hero, oldLvs); //成长任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_STRENGTHEN, 1, changeData) const curHero = { hid, ePlace: strengthenArr } return resResult(STATUS.SUCCESS, { curHero }); } // 装备栏精炼 public async refine(msg: { hid: number, ePlaceId: number, type: REFINE_TYPE }, session: BackendSession) { let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let serverId = session.get('serverId'); let sid: string = session.get('sid'); let { hid, ePlaceId, type } = msg; let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); if (!hero) return resResult(STATUS.HERO_NOT_FIND); let { ePlace } = hero; // 装备栏 let curEplace = ePlace.find(cur => cur.id == ePlaceId); if (!curEplace) { return resResult(STATUS.ROLE_EQUIP_PLACE_NOT_ENOUGH); } let { lv, refineLv: oldRefineLv, equip } = curEplace; // 强化等级,精炼等级,精炼次数 let check = new CheckMeterial(roleId); let refineLv = oldRefineLv, times = 0; while( (type == REFINE_TYPE.ONCE && times == 0) || (type == REFINE_TYPE.ONE_LEVEL && !checkRefineReachNextLv(oldRefineLv, refineLv) ) ) { let result = await refineOnce(lv, refineLv); if(!result) break; let isEnough = await check.decrease(result.consumes); if(!isEnough) break; // 消耗不足 refineLv = result.refineLv; times ++; } if(times == 0) { return resResult(STATUS.EQUIP_REFINE_ERR); } let consumes = check.getConsume(); let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); curEplace.refineLv = refineLv; await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace }); const curHero = { hid, ePlace: [curEplace] } let curEquip = equip; pushEquipRefineSucMsg(roleId, roleName, serverId, curEplace, curEquip ? curEquip.quality : 0); await checkTask(roleId, sid, TASK_TYPE.EQUIP_REFINE, times, true, {}); await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_REFINE_LV, times, { lv: curEplace.refineLv }); return resResult(STATUS.SUCCESS, { curHero }); } // 装备洗炼锁定 public async lockRandSe(msg: { eid: number, id: number, lock: boolean }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let { eid, id, lock } = msg; let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let { randSe } = equip; if (!randSe || randSe.length <= 0) { return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE); } let curSe = randSe.find(cur => cur.id == id); if (!curSe || lock == curSe.locked) { return resResult(STATUS.ROLE_EQUIP_DUPLICATE_LOCK); } if (lock) { // 仅在上锁时消耗,根据已有的锁的数量判断消耗 let lockNum = randSe.filter(cur => cur.locked).length; let consumes: Array<{ id: number, count: number }> = []; if (lockNum == 0) { consumes = parseGoodStr(EQUIP.EQUIP_ONE_LOCKED); } else if (lockNum == 1) { consumes = parseGoodStr(EQUIP.EQUIP_TWO_LOCKED); } else if (lockNum == 2) { consumes = parseGoodStr(EQUIP.EQUIP_THREE_LOCKED); } else { return resResult(STATUS.ROLE_ALL_SE_LOCK); } let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); } let result = await EquipModel.lock(roleId, eid, id, lock); if (!result) { return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE); } return resResult(STATUS.SUCCESS, { curEquip: result }); } // 装备洗炼预览 public async previewStrengthen(msg: { eid: number }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let { eid } = msg; let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let { id, randSe, previewRandSe } = equip; if(previewRandSe.length <= 0) { if (!randSe || randSe.length <= 0) { return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE); } let previewRandSe = getRandSeResult(id, randSe); if(!previewRandSe) return resResult(STATUS.DIC_DATA_NOT_FOUND); let lockNum = randSe.reduce((pre, cur) => { return cur.locked? pre + 1: pre; }, 0); if (lockNum >= randSe.length) { return resResult(STATUS.ROLE_EQUIP_CANNOT_RESTRENGTHEN); } // 消耗 let consumes: Array<{ id: number, count: number }> = []; if (lockNum == 0) { consumes = parseGoodStr(EQUIP.EQUIP_ONE_REFORGED); } else if (lockNum == 1) { consumes = parseGoodStr(EQUIP.EQUIP_TWO_REFORGED); } else if (lockNum == 2) { consumes = parseGoodStr(EQUIP.EQUIP_THREE_REFORGED); } else { consumes = parseGoodStr(EQUIP.EQUIP_FOUR_REFORGED); } let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); equip = await EquipModel.updateEquipInfo(eid, { previewRandSe }); } return resResult(STATUS.SUCCESS, { curEquip: pick(equip, ['seqId', 'id', 'randSe', 'previewRandSe']) }); } // 装备洗炼 public async reStrengthen(msg: { eid: number }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let { eid } = msg; let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let { randSe, hid, ePlaceId, previewRandSe } = equip; if (!randSe || randSe.length <= 0) { return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE); } if(!previewRandSe) { // 没预览过 return resResult(STATUS.EQUIP_RESTRENGTHEN_NOT_PREVIEW); } let removeSeidList = randSe.reduce((pre, cur) => { return [...pre, cur.seid]; }, []); let equipResult = await EquipModel.updateEquipInfo(eid, { randSe: previewRandSe, previewRandSe: [] }) // 更新战力 if(hid > 0) { const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.RESTRENGTHEN, sid, roleId, hero, {}, [ePlaceId, ...removeSeidList]); } await checkTask(roleId, sid, TASK_TYPE.EQUIP_RESTRENGTHEN, 1, true, {}); return resResult(STATUS.SUCCESS, { curEquip: pick(equipResult, ['seqId', 'id', 'randSe', 'previewRandSe']) }); } // 放弃这条洗练 public async giveupStrengthen(msg: { eid: number }, session: BackendSession) { let { eid } = msg; let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let { randSe, previewRandSe } = equip; if (!randSe || randSe.length <= 0) { return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE); } if(!previewRandSe) { // 没预览过 return resResult(STATUS.EQUIP_RESTRENGTHEN_NOT_PREVIEW); } let equipResult = await EquipModel.updateEquipInfo(eid, { previewRandSe: [] }) return resResult(STATUS.SUCCESS, { curEquip: pick(equipResult, ['seqId', 'id', 'randSe', 'previewRandSe']) }); } // 淬火 public async quench(msg: { eid: number, type: QUENCH_TYPE }, session: BackendSession) { let roleId: string = session.get('roleId'); // let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let { eid, type } = msg; let equip = await EquipModel.findbySeqId(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let { id, randMain, grade, hid, ePlaceId } = equip; let dicGoods = gameData.goods.get(id); if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND); let dicQuench = gameData.quenchByQuality.get(dicGoods.quality)?.get(grade); // console.log(dicQuench, dicGoods.quality, grade) if (!dicQuench) return resResult(STATUS.EQUIP_QUENCH_MAX); let check = new CheckMeterial(roleId); let logs: QuenchLogParam[] = [], times = 0; while( (type == QUENCH_TYPE.ONCE && times < 1 && !checkQuenchMaxByQualityAndGrade(dicGoods.quality, 0, randMain)) || // 淬火一次,保证不超出该品质上限 (type == QUENCH_TYPE.ONE_GRADE && !checkQuenchMaxByQualityAndGrade(dicGoods.quality, grade, randMain)) // 淬火一品,在品相上限内淬火 ) { let result = await quenchOnce(randMain, dicQuench, dicGoods); if(!result) break; let isEnough = await check.decrease(result.consumes); if(!isEnough) break; // 消耗不足 result.log.setTimes(++times); logs.push(result.log); grade = result.grade; randMain = result.randMain; } if (times == 0) return resResult(STATUS.EQUIP_QUENCH_ERR); let consumes = check.getConsume(); let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); let equipResult = await EquipModel.updateEquipInfo(eid, { randMain, grade }) let curEquip = { seqId: equipResult.seqId, id: equipResult.id, randMain: equipResult.randMain, grade: equipResult.grade, } // 更新战力 if(hid > 0) { // 装备中的时候 const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { }); } return resResult(STATUS.SUCCESS, { logs, curEquip }); } //分解装备 public async decomposeEquip(msg: { originalEquip: Array }, session: BackendSession) { let { originalEquip } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); if(originalEquip.length > BAG.BAG_RESOLVE_UPLIMITED) { return resResult(STATUS.EQUIP_DECOMPOSE_IS_UPLIMIT); } let equips = await EquipModel.getEquips(roleId, originalEquip); if (equips.length < originalEquip.length) return resResult(STATUS.EQUIP_NOT_FIND); let goods: Array<{ id: number, count: number }> = []; let cost: ItemInter[] = []; let jewels: ItemInter[] = []; // 宝石返还 for (let equip of equips) { if (!!equip.hid) return resResult(STATUS.EQUIP_IS_EQUIPED_NOT_DECOMPOSE); let goodInfo = getGoodById(equip.id); if (!goodInfo) return resResult(STATUS.EQUIP_NOT_FIND); let holes = equip.holes || []; for (let { jewel } of holes) { if(jewel) { jewels.push({ id: jewel, count: 1 }); } } goods = goods.concat(goodInfo.decomposeItem); cost.push({ seqId: equip.seqId, id: equip.id, count: 1 }); } let costResult = await handleCost(roleId, sid, cost); // 删掉装备 if(!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); await addItems(roleId, roleName, sid, jewels); // 把原本镶嵌在装备上的宝石返还了 let result = await addItems(roleId, roleName, sid, goods); return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); } public async decomposeEquipPiece(msg: { originalPiece: { id: number, count: number }[] }, session: BackendSession) { let { originalPiece } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let goods: ItemInter[] = []; for (let { id, count } of originalPiece) { let goodInfo = getGoodById(id); if (!goodInfo) return resResult(STATUS.DIC_DATA_NOT_FOUND); let dicItid = ITID.get(goodInfo.itid); if(!dicItid || dicItid.type != CONSUME_TYPE.PIECE) { return resResult(STATUS.CONSUME_TYPE_ERR); } for(let result of goodInfo.decomposeItem) { goods.push({ id: result.id, count: result.count * count }); } } let costResult = await handleCost(roleId, sid, originalPiece); if(!costResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); let result = await addItems(roleId, roleName, sid, goods); return resResult(STATUS.SUCCESS, { goods: combineItems(result) }); } //穿戴或卸载装备 1-穿上装备(包括替换) 2-脱下装备 public async putOnOrOff(msg: { eid: number, hid: number, type: number }, session: BackendSession) { let { eid, hid, type } = msg; let roleId: string = session.get('roleId'); let serverId: number = session.get('serverId'); let sid: string = session.get('sid'); // 原武将:heroA,原武将穿戴着的装备a,将要穿戴的装备b,装备b被装备着的武将B let heroA = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); if (!heroA) return resResult(STATUS.HERO_NOT_FIND); let equip = await EquipModel.getEquip(eid); // 装备:1-equipB 2-equipA if(!equip) return resResult(STATUS.EQUIP_NOT_FIND); let argsA = calEquipSeids(heroA); let heroB: HeroType, equipA: EquipType, equipB: EquipType, argsB: number[] = []; let heroAPutNum = 0, heroBPutTNum = 0; // 1:多一件 0:没变化 -1:少一件 let goodInfo = getGoodById(equip.id); let obj = ITID.get(goodInfo.itid); let eplaceId = obj.type; // 位置 if (type == 1) { equipB = equip; // 要穿上的装备 if (equipB.hid == hid) return resResult(STATUS.WRONG_PARMS); if(!checkEquipCanPut(heroA, equipB.id)) return resResult(STATUS.EQUIP_NOT_EQUIPED_HERO); let index = heroA.ePlace.findIndex(cur => cur.id == eplaceId); if (index == -1) return resResult(STATUS.WRONG_PARMS); equipA = heroA.ePlace[index].equip; // 要脱下的装备 if(equipB.hid > 0) { heroB = await HeroModel.findByHidAndRoleWithEquip(equipB.hid, roleId); argsB = calEquipSeids(heroB); } if(equipA) { if(equipB.hid > 0) { if(checkEquipCanPut(heroB, equipA.id)) { // A=>b & B=>a equipA = await EquipModel.putOnOrOff(equipA._id, equipB.hid); heroB = await HeroModel.addEquip(roleId, heroB.hid, eplaceId, equipA._id); } else { // A=>b & B=>0 & 0=>a equipA = await EquipModel.putOnOrOff(equipA._id, 0); heroB = await HeroModel.removeEquip(roleId, equipB.hid, eplaceId); heroBPutTNum = -1; } } else { // A=>b & 0=>a equipA = await EquipModel.putOnOrOff(equipA._id, 0); } } else { if(equipB.hid > 0) { // A=>b & B=>0 heroB = await HeroModel.removeEquip(roleId, equipB.hid, eplaceId); heroBPutTNum = -1; } // A=>b heroAPutNum = 1; } heroA = await HeroModel.addEquip(roleId, heroA.hid, eplaceId, equipB._id); equipB = await EquipModel.putOnOrOff(equipB._id, heroA.hid); } else if (type == 2) { // A=>0 & 0=>a if (!equip.hid) return resResult(STATUS.EQUIP_NOT_EQUIPED); equipA = await EquipModel.putOnOrOff(equip._id, 0); heroA = await HeroModel.removeEquip(roleId, heroA.hid, eplaceId); heroAPutNum = -1; } if(heroA) { await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, heroA, {}, argsA); if(heroAPutNum != 0) { await checkTaskWithHero(roleId, sid, TASK_TYPE.EQUIP_BY_HERO, heroA, [heroAPutNum]); } } if(heroB) { await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, heroB, {}, argsB); if(heroBPutTNum != 0) await checkTaskWithHero(roleId, sid, TASK_TYPE.EQUIP_BY_HERO, heroA, [heroBPutTNum]); } if(heroAPutNum + heroBPutTNum != 0) { await checkTask(roleId, sid, TASK_TYPE.EQUIP_SUM, heroAPutNum + heroBPutTNum, true, {}); await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_SUM, heroAPutNum + heroBPutTNum) } let curEquips: Array<{ seqId: number, hid: number }> = []; if(equipA) { curEquips.push(pick(equipA, ['seqId', 'hid'])); if(equipA.hid == 0) { await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_QUALITY, equipA, [-1]); // equipA必然是脱,如果hid不为0说明从一个人穿到另一个人,不算任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_QUALITY, 1, { quality: equipA.quality }); } } if(equipB) { curEquips.push(pick(equipB, ['seqId', 'hid'])); if(equipB.hid != 0) { await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_QUALITY, equipB, [1]); // equipB必然是穿,如果hid为0说明没有变化,不算任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_QUALITY, 1, { quality: equipB.quality }); } } if(type == 1) { let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(heroA)//英雄满装备且都镶嵌相同阶数的宝石 if (isTask) { await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel }) } } return resResult(STATUS.SUCCESS, { curEquips: curEquips }); } // 一次性装备上 public async putOnOnce(msg: { hid: number }, session: BackendSession) { let { hid } = msg; let roleId: string = session.get('roleId'); const serverId = session.get('serverId'); let sid: string = session.get('sid'); let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId); if (!hero) return resResult(STATUS.HERO_NOT_FIND); let args = calEquipSeids(hero); let dicHero = gameData.hero.get(hid); if (!dicHero) return resResult(STATUS.DIC_DATA_NOT_FOUND); let dicJob = gameData.job.get(dicHero.jobid); let allEquips = await EquipModel.findNotWearEquips(roleId); let sortEquips = allEquips.map(equip => { let { id, quality, ePlaceId, randMain } = equip; let { goodsAbility, lvLimited } = gameData.goods.get(id); let ce = calEquipCe(goodsAbility, randMain); return { id, quality, ce, equip, goodsAbility, lvLimited, ePlaceId } }); let { ePlace, lv } = hero; let curEquips: Array<{ seqId: number, hid: number }> = []; for (let curEPlace of ePlace) { if (!curEPlace.equip) { // 未装备 let sortAttrId = equipTypeToSortAttr.get(curEPlace.id); let sortedAndSuitEquips = sortEquips.filter(equipInfos => { // 筛选可穿的 let { id, lvLimited, ePlaceId } = equipInfos; return lv >= lvLimited && checkEquipCanPut(hero, id) && curEPlace.id == ePlaceId; }); // console.log('sortedAndSuitEquips', JSON.stringify(sortedAndSuitEquips, null, 4)) sortedAndSuitEquips = sortedAndSuitEquips.sort((a, b) => { // 排序按:战力 => 根据位置看个别属性 => 品质 if (b.ce - a.ce != 0) return b.ce - a.ce; let abilityA = a.goodsAbility.get(sortAttrId) || 0; let abilityB = b.goodsAbility.get(sortAttrId) || 0; if (abilityA - abilityB != 0) return abilityB - abilityA; return b.quality - a.quality; }); if (sortedAndSuitEquips.length > 0) { let { equip } = sortedAndSuitEquips.shift(); hero = await HeroModel.addEquip(roleId, hero.hid, equip.ePlaceId, equip._id); equip = await EquipModel.putOnOrOff(equip._id, hero.hid); if (!!equip) curEquips.push(pick(equip, ['seqId', 'hid'])); } } } if (curEquips.length > 0) { //任务 //英雄满装备且都镶嵌相同阶数的宝石 let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(hero) if (isTask) { await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel }) } await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, hero, {}, args); } return resResult(STATUS.SUCCESS, { curEquips }); } //装备打孔 public async digHole(msg: { eid: number, id: number }, session: BackendSession) { let { eid, id } = msg; let roleId: string = session.get('roleId'); let sid: string = session.get('sid'); let equip = await EquipModel.getEquip(eid); let index = findIndex(equip.holes, { id }); if (index < 0) return resResult(STATUS.EQUIP_HOLE_NOT_FIND); if (equip.holes[index].isOpen) return resResult(STATUS.EQUIP_HOLE_IS_DUG); let consumes: Array<{ id: number, count: number }> = []; if (id == 1) { consumes = parseGoodStr(EQUIP.EQUIP_ONE_HOLE); } else if (id == 2) { consumes = parseGoodStr(EQUIP.EQUIP_TWO_HOLE); } else if (id == 3) { consumes = parseGoodStr(EQUIP.EQUIP_THREE_HOLE); } let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); equip.holes[index].isOpen = true; await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } //宝石镶嵌 public async fillHole(msg: { eid: number, id: number, jewel: number }, session: BackendSession) { let { eid, id, jewel } = msg; let roleId: string = session.get('roleId'); const serverId = session.get('serverId'); let sid: string = session.get('sid'); let consumes: Array<{ id: number, count: number }> = []; let goods: Array<{ id: number, count: number }> = []; let equip = await EquipModel.getEquip(eid); let oldJewelCount = equip.holes.filter(cur => cur.jewel > 0).length; let { itid } = getGoodById(equip.id); let { equipJewel } = ITID.get(itid); let jewelInfo = getGoodById(jewel); if (jewelInfo.itid != equipJewel) return resResult(STATUS.EQUIP_NOT_MATCH_JEWEL); let index = findIndex(equip.holes, { id }); if (index < 0) return resResult(STATUS.EQUIP_HOLE_NOT_FIND); if (!equip.holes[index].isOpen) return resResult(STATUS.EQUIP_HOLE_IS_NOT_DUG); let oldJewel = equip.holes[index].jewel; if (!!oldJewel) goods.push({ id: oldJewel, count: 1 }); consumes.push({ id: jewel, count: 1 }); let result = await handleCost(roleId, sid, consumes); if (!result) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); equip.holes[index].jewel = jewel; await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); let roleName: string = session.get('roleName'); if (goods.length) await addItems(roleId, roleName, sid, goods); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRoleWithEquip(equip.hid, roleId); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]); //任务 //英雄满装备且都镶嵌相同阶数的宝石 let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(hero) if (isTask) { await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel }) } } // 任务 await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]); await checkTaskWithArgs(roleId, sid, TASK_TYPE.EQUIP_JEWEL_STAGE, [jewel, oldJewel]); await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL_SUM, equip, [oldJewelCount]); //成长任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_JEWEL_SUM, 1) await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_JEWEL_STAGE, 1) return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } //宝石合成(一键放入type:1, 合成type:2) public async composeJewel(msg: { jewel: number, count: number, consumes: Array<{ id: number, count: number }>, type: number }, session: BackendSession) { let { count, consumes, jewel, type } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let serverId: number = session.get('serverId'); let sid: string = session.get('sid'); let goodInfo = getGoodById(jewel); let good = ITID.get(goodInfo.itid); if (good.type != CONSUME_TYPE.JEWEL) return resResult(STATUS.WRONG_PARMS); let needConsumes = checkMaterialEnough(consumes, jewel, count);//检查是否可以合成,并返回最终需要消耗的材料 if (!needConsumes) return resResult(STATUS.WRONG_PARMS); let res = await handleCost(roleId, sid, needConsumes); if (!res) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); let result = await addItems(roleId, roleName, sid, [{ id: jewel, count: count }]); if (goodInfo.lvLimited >= JEWEL_PUSH_LV) { pushNormalItemMsg(roleId, roleName, serverId, MSG_SOURCE.JEWEL_COMPOSE, jewel, goodInfo.name); } if (type == 1) return resResult(STATUS.SUCCESS, { goods: result }); return resResult(STATUS.SUCCESS); } //宝石卸下 public async putOffHole(msg: { eid: number, id: number }, session: BackendSession) { let { eid, id } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let goods: Array<{ id: number, count: number }> = []; let equip = await EquipModel.getEquip(eid); let oldJewelCount = equip.holes.filter(cur => cur.jewel > 0).length; let index = findIndex(equip.holes, { id }); if (index < 0) return resResult(STATUS.EQUIP_HOLE_NOT_FIND); let jewel = equip.holes[index].jewel; if (!jewel) return resResult(STATUS.EQUIP_NOT_FILL_HOLE); goods.push({ id: jewel, count: 1 }); equip.holes[index].jewel = 0; await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); await addItems(roleId, roleName, sid, goods); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRole(equip.hid, roleId); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_OFF, sid, roleId, hero, {}, [jewel]); } // 任务 await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]); await checkTaskWithArgs(roleId, sid, TASK_TYPE.EQUIP_JEWEL_STAGE, [0, jewel]); await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL_SUM, equip, [oldJewelCount]); return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } //宝石购买并合成 public async composeAndPurchaseJewel(msg: { jewel: number, count: number, consumes: Array<{ id: number, count: number }>, purchaseGoods: Array<{ id: number, count: number }> }, session: BackendSession) { let { count, consumes, jewel, purchaseGoods } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); const serverId = session.get('serverId'); let goodInfo = getGoodById(jewel); let good = ITID.get(goodInfo.itid); if (good.type != CONSUME_TYPE.JEWEL) return resResult(STATUS.WRONG_PARMS); if (!purchaseGoods) //需要购买才可进行合成的物品 purchaseGoods = []; if (!consumes) consumes = []; let needConsumes = checkMaterialEnough(consumes.concat(purchaseGoods), jewel, count);//检查是否可以合成,并返回最终需要消耗的材料 if (!needConsumes) return resResult(STATUS.WRONG_PARMS); let items: Array<{ id: number, count: number, ratio?: number }> = []; for (let item of purchaseGoods) { items.push({ id: item.id, count: item.count, ratio: 1 })//加上购买的数量 } items = items.concat(needConsumes); let hasError = await decreaseItems(roleId, sid, items);//合并消耗是否足够 if (!!hasError) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); await addItems(roleId, roleName, sid, [{ id: jewel, count: count }]); if (goodInfo.lvLimited >= JEWEL_PUSH_LV) { pushNormalItemMsg(roleId, roleName, serverId, MSG_SOURCE.JEWEL_COMPOSE, jewel, goodInfo.name); } return resResult(STATUS.SUCCESS); } /** * 临时使用的购买物品,后应该在商店中购买 * @param msg * @param session */ public async purchaseGoods(msg: { purchaseGoods: Array<{ id: number, count: number }> }, session: BackendSession) { let { purchaseGoods } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let result = await addItems(roleId, roleName, sid, purchaseGoods); if (!result) { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); } return resResult(STATUS.SUCCESS); } /** * 合成下一级宝石并穿戴(装备镶嵌界面) * @param msg * @param session */ public async composeNextLevelJewel(msg: { jewel: number, count: number, eid: number, id: number }, session: BackendSession) { let { count, jewel, eid, id } = msg; let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); let serverId = session.get('serverId'); let goodInfo = getGoodById(jewel); let good = ITID.get(goodInfo.itid); let needUpdate = false; let oldJewel: number; let consumes: Array<{ id: number, count: number, ratio?: number }> = []; if (good.type != CONSUME_TYPE.JEWEL || !eid || eid < 0) return resResult(STATUS.WRONG_PARMS); let equip = await EquipModel.getEquip(eid); if (!equip) return resResult(STATUS.EQUIP_NOT_FIND); let oldJewelCount = equip.holes.filter(cur => cur.jewel > 0).length; let index = findIndex(equip.holes, { id }); //装备上该位置有穿戴该宝石,且在合成的材料中 if (!!equip.holes[index] && equip.holes[index].jewel == goodInfo.composeMaterial[0].id) { oldJewel = equip.holes[index].jewel; equip.holes[index].jewel = jewel;//合成后的新宝石穿戴到装备上 needUpdate = true; consumes.push({ id: goodInfo.composeMaterial[0].id, count: 1, ratio: 1 });//ratio:1表示可以释放掉一颗宝石 } consumes = consumes.concat(goodInfo.composeMaterial); if (goodInfo.specialMaterial.count) { consumes.push({ id: goodInfo.specialMaterial.ids[0], count: goodInfo.specialMaterial.count }) } let hasError = await decreaseItems(roleId, sid, consumes);//检查是消耗是否足够 if (!!hasError) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); if (goodInfo.lvLimited >= JEWEL_PUSH_LV) { pushNormalItemMsg(roleId, roleName, serverId, MSG_SOURCE.JEWEL_COMPOSE, jewel, goodInfo.name); } let result = {}; if (needUpdate) { //穿戴宝石 equip = await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); if (!!equip.hid) { let hero = await HeroModel.findByHidAndRoleWithEquip(equip.hid, roleId); await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]); //任务 //英雄满装备且都镶嵌相同阶数的宝石 let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(hero) if (isTask) { await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel }) } } // 任务 await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]); await checkTaskWithArgs(roleId, sid, TASK_TYPE.EQUIP_JEWEL_STAGE, [jewel, oldJewel]); await checkTaskWithEquip(roleId, sid, TASK_TYPE.EQUIP_JEWEL_SUM, equip, [oldJewelCount]); //成长任务 await checkActivityTask(serverId, sid, roleId, TASK_TYPE.EQUIP_JEWEL_SUM, count) return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } }); } else { result = await addItems(roleId, roleName, sid, [{ id: jewel, count: count }]); return resResult(STATUS.SUCCESS, { goods: [{ id: jewel, count }] }); } } /** * @description 藏宝图合成 * @param {{target: number, original: Array<{id: number, count: number}>}} msg * @param {BackendSession} session * @returns * @memberof ComBattleHandler */ async composeBlueprt(msg: { target: number, original: Array<{ id: number, count: number }> }, session: BackendSession) { const roleId = session.get('roleId'); const roleName = session.get('roleName'); const sid = session.get('sid'); const serverId = session.get('serverId'); const { target, original } = msg; // 原材料检查 let originalQuality: number, originalSum: number = 0; for (let { id, count } of original) { const goodInfo = gameData.goods.get(id); if (!originalQuality) originalQuality = goodInfo.quality; if (originalQuality != goodInfo.quality) { return resResult(STATUS.COM_BLUEPRT_QUALITY_ERROR); } if (goodInfo.itid == IT_TYPE.BLUEPRT) { originalSum += count; } } const dicCompose = gameData.blurprtCompose.get(originalQuality); if (!dicCompose) { return resResult(STATUS.COM_BLUEPRT_QUALITY_CANNOT_COMPOSE); } if (originalSum != dicCompose.blueprtNum) { return resResult(STATUS.COM_BLUEPRT_COUNT_ERROR); } let dicTargetInfo = gameData.goods.get(target); if (!dicTargetInfo) return resResult(STATUS.WRONG_PARMS); if (dicTargetInfo.quality != dicCompose.targetQuality) return resResult(STATUS.COM_BLUEPRT_QUALITY_ERROR); // 消耗藏宝图和寻宝币 let costResult = await handleCost(roleId, sid, [...original, ...dicCompose.coinNum]); if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); const reward = [{ id: target, count: 1 }]; const goods = await addItems(roleId, roleName, sid, reward); if (dicCompose.targetQuality >= QUALITY_TYPE.ORANGE) { const { name } = gameData.goods.get(target); pushNormalItemMsg(roleId, roleName, serverId, MSG_SOURCE.ORANGE_BLUEPRT_COMPOSE, target, name); } await checkTask(roleId, sid, TASK_TYPE.COM_BATTLE_BLUEPRT, 1, true, { quality: dicCompose.targetQuality }); return resResult(STATUS.SUCCESS, { goods, costGold: 0 }); } }