Files
ZYZ/game-server/app/servers/role/handler/equipHandler.ts
2021-07-16 11:29:26 +08:00

938 lines
41 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, getRandValueByMinMax, getRandEelm } from "../../../pubUtils/util";
import { addItems, handleCost, decreaseItems } from "../../../services/rewardService";
import Equip, { EquipModel, EquipType } from "../../../db/Equip";
import { HeroModel, EPlace } from "../../../db/Hero";
import Role from "../../../db/Role";
import { calPlayerCeAndSave } from "../../../services/playerCeService";
import { getHeroJob, getGoodById, gameData, getHeroEquipByClassId } from "../../../pubUtils/data";
import { EQUIP } from "../../../pubUtils/dicParam";
import { ITID, SPEICAL_ITEM, QUALITY_TYPE, equipTypeToSortAttr, IT_TYPE } from "../../../consts/constModules/itemConst";
import { changeEquip, dressEquip, checkMaterialEnough, takeOffEquipAndCalPlayerCe } from "../../../services/equipService";
import { indexOf, findIndex } from 'underscore';
import { pushEquipRefineSucMsg, pushNormalEquipMsg, pushNormalItemMsg } from "../../../services/chatService";
import { checkTaskWithHero, checkTaskWithEquip, checkTask, checkTaskWithArgs, checkTaskConditionEquipSuitJewelStage, checkActivityTask } from "../../../services/taskService";
import { Attribute } from "../../../domain/roleField/attribute";
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(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 funcs: number[] = session.get('funcs');
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<EPlace>();
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, funcs, TASK_TYPE.EQUIP_STRENGTHEN, hero, oldLvs);
//成长任务
await checkActivityTask(serverId, sid, funcs, 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');
let funcs: number[] = session.get('funcs');
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, funcs, TASK_TYPE.EQUIP_STRENGTHEN, hero, oldLvs);
//成长任务
await checkActivityTask(serverId, sid, funcs, 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, material: { id: number, count: number }[] }, 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 funcs: number[] = session.get('funcs');
let { hid, ePlaceId, material } = 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, equip } = curEplace; // 强化等级,精炼等级,精炼次数
if (lv < HERO_GROW_MAX.EQUIP_STRENGTHEN) {
return resResult(STATUS.ROLE_EQUIP_NOT_REACH_MAX);
}
if (refineLv >= HERO_GROW_MAX.EQUIP_REFINE) {
return resResult(STATUS.ROLE_EQUIP_REACH_MAX);
}
// 是否成功精炼
let dicRefine = gameData.refine.get(refineLv + 1);
if (!dicRefine) {
return resResult(STATUS.DIC_DATA_NOT_FOUND)
}
let { successRate } = dicRefine;
for (let { id, count } of material) {
let dicGoods = gameData.goods.get(id);
if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND);
if (!SPEICAL_ITEM.REFINE_ADD_RATE.includes(id)) {
return resResult(STATUS.ROLE_WRONG_ITEM)
}
successRate += count * dicGoods.value;
if (isNaN(successRate)) console.error(id, count, dicGoods.value);
}
let ran = Math.floor(Math.random() * 100);
let isSuccess = ran <= successRate;
// 消耗道具提升成功率 每个道具提升10%成功率
// 精炼
if (isSuccess) {
curEplace.refineLv++;
}
// 消耗
let cost = dicRefine.material.concat(material);
let result = await handleCost(roleId, sid, cost);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace });
const curHero = {
hid,
ePlace: [curEplace]
}
if (isSuccess) {
let curEquip = <EquipType>equip;
pushEquipRefineSucMsg(roleId, roleName, serverId, curEplace, curEquip ? curEquip.quality : 0);
await checkTask(roleId, sid, funcs, TASK_TYPE.EQUIP_REFINE, 1, true, {});
await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.EQUIP_REFINE_LV, 1, { lv: curEplace.refineLv });
}
return resResult(STATUS.SUCCESS, { isSuccess, 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 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 funcs: number[] = session.get('funcs');
let { eid } = msg;
let equip = await EquipModel.findbySeqId(eid);
if (!equip) return resResult(STATUS.EQUIP_NOT_FIND);
let { id, randSe, hid, ePlaceId } = equip;
if (!randSe || randSe.length <= 0) {
return resResult(STATUS.ROLE_EQUIP_HAVE_NO_RANDSE);
}
let dicGoods = gameData.goods.get(id);
if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let { randomEffect } = dicGoods;
let chosen = randSe.map(cur => cur.seid); // 上一轮随机出来的
let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), randSe.length);
let lockNum = 0;
let removeSeidList = new Array<number>(); // 原装备上的seid [seid, rand, ...]
for (let i = 0; i < randSe.length; i++) {
removeSeidList.push(randSe[i].seid, randSe[i].rand);
if (!randSe[i].locked) {
let random = gameData.randomEffectPool.get(randomResult[i]);
if (!random) break;
let rand = 0;
if (random.id > 0) rand = getRandValueByMinMax(random.Min, random.Max, 0);
randSe[i].seid = random.id;
randSe[i].rand = rand;
} else {
lockNum++;
}
}
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);
let equipResult = await EquipModel.updateEquipInfo(eid, { randSe })
let curEquip = {
seqId: equipResult.seqId,
id: equipResult.id,
randSe: equipResult.randSe
}
// 更新战力
const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.RESTRENGTHEN, sid, roleId, hero, {}, [ePlaceId, ...removeSeidList]);
await checkTask(roleId, sid, funcs, TASK_TYPE.EQUIP_RESTRENGTHEN, 1, true, {});
return resResult(STATUS.SUCCESS, { curEquip });
}
//分解装备
public async decomposeEquip(msg: { originalEquip: Array<number> }, session: BackendSession) {
let { originalEquip } = msg;
let roleId: string = session.get('roleId');
let roleName: string = session.get('roleName');
let sid: string = session.get('sid');
let equips = await EquipModel.getEquips(originalEquip);
if (equips.length < originalEquip.length)
return resResult(STATUS.EQUIP_NOT_FIND);
let goods: Array<{ id: number, count: number }> = [];
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) {
jewels.push({ id: jewel, count: 1 });
}
goods = goods.concat(goodInfo.decomposeItem);
}
let uids = [{ uid: roleId, sid }];
await EquipModel.deleteEquips(originalEquip);
this.app.get('channelService').pushMessageByUids('onEquipDel', resResult(STATUS.SUCCESS, { equips: originalEquip }), uids);
await addItems(roleId, roleName, sid, jewels); // 把原本镶嵌在装备上的宝石返还了
let result = await addItems(roleId, roleName, sid, goods);
return resResult(STATUS.SUCCESS, { goods: 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');
const serverId = session.get('serverId');
let equip = await EquipModel.getEquip(eid);
let sid: string = session.get('sid');
let funcs: number[] = session.get('funcs');
let goodInfo = getGoodById(equip.id);
let obj = ITID.get(goodInfo.itid);
let id = obj.type;
let curEquips: Array<{ seqId: number, hid: number }> = [];
let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId);
if (!hero)
return resResult(STATUS.HERO_NOT_FIND);
if (type == 1) {
if (equip.hid == hid)
return resResult(STATUS.WRONG_PARMS);
if (goodInfo.lvLimited > hero.lv)
return resResult(STATUS.EQUIP_LEVEL_LIMIT);
let { jobid } = gameData.hero.get(hid);
let { job_class } = getHeroJob(jobid);
let { classId } = getHeroEquipByClassId(goodInfo.itid);
if (indexOf(classId, job_class) < 0)
return resResult(STATUS.EQUIP_NOT_EQUIPED_HERO);
let index = findIndex(hero.ePlace, { id });
if (index < 0)
return resResult(STATUS.WRONG_PARMS);
let equipOffInfo = <EquipType>hero.ePlace[index].equip;
let curEquip = await changeEquip(serverId, roleId, sid, equipOffInfo, equip.hid, id, equip, funcs);
if (!!curEquip)
curEquips.push(curEquip);
curEquip = await dressEquip(serverId, roleId, sid, hero, equip, funcs);
if (!!curEquip)
curEquips.push(curEquip);
//任务
//英雄满装备且都镶嵌相同阶数的宝石
let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(hero)
if (isTask) {
await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel })
}
} else if (type == 2) {
if (!equip.hid)
return resResult(STATUS.EQUIP_NOT_EQUIPED);
let curEquip = await takeOffEquipAndCalPlayerCe(roleId, sid, hero, equip, id, funcs);
curEquips.push(curEquip);
}
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 funcs: number[] = session.get('funcs');
let hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
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, randRange, ePlaceId } = equip;
let { goodsAbility, lvLimited, itid } = gameData.goods.get(id);
let attrObj = new Attribute();
attrObj.setByMap(goodsAbility, HERO_CE_RATIO + randRange);
let ce = attrObj.calEquipCe();
let { classId } = getHeroEquipByClassId(itid);
return { id, quality, ce, equip, goodsAbility, lvLimited, classId, 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 { lvLimited, classId, ePlaceId } = equipInfos;
return lv >= lvLimited && classId.indexOf(dicJob.job_class) != -1 && curEPlace.id == ePlaceId;
}).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();
let curEquip = await dressEquip(serverId, roleId, sid, hero, equip, funcs);
if (!!curEquip) curEquips.push(curEquip);
}
}
}
if (curEquips.length > 0) {
//任务
//英雄满装备且都镶嵌相同阶数的宝石
let { isTask, jewelLevel } = await checkTaskConditionEquipSuitJewelStage(hero)
if (isTask) {
await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel })
}
}
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 funcs: number[] = session.get('funcs');
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, funcs, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel })
}
}
// 任务
await checkTaskWithEquip(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]);
await checkTaskWithArgs(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL_STAGE, [jewel, oldJewel]);
await checkTaskWithEquip(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL_SUM, equip, [oldJewelCount]);
//成长任务
await checkActivityTask(serverId, sid, funcs, roleId, TASK_TYPE.EQUIP_JEWEL_SUM, 1)
await checkActivityTask(serverId, sid, funcs, 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 funcs: number[] = session.get('funcs');
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, funcs, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]);
await checkTaskWithArgs(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL_STAGE, [0, jewel]);
await checkTaskWithEquip(roleId, sid, funcs, 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 funcs: number[] = session.get('funcs');
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 });//ratio1表示可以释放掉一颗宝石
}
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, funcs, roleId, TASK_TYPE.EQUIP_SUIT_JEWEL_STAGE, 1, { stage: jewelLevel })
}
}
// 任务
await checkTaskWithEquip(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL, equip, [oldJewelCount]);
await checkTaskWithArgs(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL_STAGE, [jewel, oldJewel]);
await checkTaskWithEquip(roleId, sid, funcs, TASK_TYPE.EQUIP_JEWEL_SUM, equip, [oldJewelCount]);
//成长任务
await checkActivityTask(serverId, sid, funcs, 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 funcs: number[] = session.get('funcs');
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);
// 添加寻宝币
original.push({
id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.TREASURE_POINT),
count: dicCompose.coinNum
});
// 消耗藏宝图和寻宝币
let costResult = await handleCost(roleId, sid, original);
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, funcs, TASK_TYPE.COM_BATTLE_BLUEPRT, 1, true, { quality: dicCompose.targetQuality });
return resResult(STATUS.SUCCESS, { goods, costGold: 0 });
}
}