diff --git a/game-server/app/servers/role/handler/equipHandler.ts b/game-server/app/servers/role/handler/equipHandler.ts index 672762574..ecc503aed 100644 --- a/game-server/app/servers/role/handler/equipHandler.ts +++ b/game-server/app/servers/role/handler/equipHandler.ts @@ -1,5 +1,5 @@ import { Application, BackendSession, HandlerService, } from "pinus"; -import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE } from "../../../consts"; +import { STATUS, HERO_SYSTEM_TYPE, ITEM_CHANGE_REASON, TASK_TYPE, CONSUME_TYPE } from "../../../consts"; import { ItemInter, RewardInter } from "../../../pubUtils/interface"; import { resResult, parseGoodStr } from "../../../pubUtils/util"; @@ -9,14 +9,17 @@ import { gameData, getEquipByJobClassAndEPlace, getNextEquipQuality, getEquipSta import { BAG, EQUIP } from "../../../pubUtils/dicParam"; import { getRandSeResult, updateEplace, updateEplaces, checkJewelCanPutOnEquip, updateStone, checkStoneCanPutOnEquip, isLocked } from "../../../services/equipService"; -import { isNumber, pick } from 'underscore'; +import { clone, isNumber, max, min, pick } from 'underscore'; import { JewelModel, RandSe } from "../../../db/Jewel"; import { checkTaskInComposeEquip, checkTaskInEquipLvUp, checkTaskInComposeStone, checkTaskInEquipReset, checkTaskInEquipQuench, checkTaskInEquipQualityUp, checkTaskInEquipStarUp, checkTaskInPutJewel, checkTaskInPutStone } from '../../../services/task/taskService'; import { pushEquipQualityMax, pushEquipStarMax } from "../../../services/sysChatService"; import { addConsumeToHero } from "../../../services/roleService"; -import { CheckMeterial } from "../../../services/role/checkMaterial"; +import { CheckMeterial, getComposeStoneCostAndAdd, getCurItem } from "../../../services/role/checkMaterial"; import { combineItems } from "../../../services/role/util"; import { calculateCeWithHero } from "../../../services/playerCeService"; +import { ItemModel } from "../../../db/Item"; +import { index } from "typegoose"; +import { all } from "bluebird"; export default function (app: Application) { new HandlerService(app, {}); @@ -735,6 +738,43 @@ export class EquipHandler { return resResult(STATUS.SUCCESS, { goods }); } + + public async composeStoneByItId(msg: { itId: number }, session: BackendSession) { + let { itId } = msg; + let roleId: string = session.get('roleId'); + let roleName: string = session.get('roleName'); + let sid: string = session.get('sid'); + let serverId: number = session.get('serverId'); + + let curItem = await getCurItem(roleId, itId); + if (curItem.size == 0) { + // console.log("---composeStoneByItId-- curItem=%s", curItem); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + let { allCostItem, allAddItem } = await getComposeStoneCostAndAdd(curItem, itId) + if (allCostItem.size == 0 || allAddItem.size == 0) { + // console.log("---composeStoneByItId-- allCostItem=%s, allAddItem=%s", allCostItem, allAddItem); + return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + } + + let costResult = await handleCost(roleId, sid, [...allCostItem].map(([id, count]) => ({ id, count })), ITEM_CHANGE_REASON.COMPOSE_STONE); + if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); + + let arrAddItem = []; + let total = 0; + for (const [id, count] of allAddItem) { + if (count == 0) continue; + arrAddItem.push({ id, count }); + total += count; + } + let goods = await addItems(roleId, roleName, sid, arrAddItem, ITEM_CHANGE_REASON.COMPOSE_STONE); + + await checkTaskInComposeStone(serverId, roleId, sid, total); + return resResult(STATUS.SUCCESS, { goods }); + } + + public async inheritJewel(msg: { originJewel: number, targetJewel: number }, session: BackendSession) { let { originJewel: originJewelId, targetJewel: targetJewelId } = msg; let roleId: string = session.get('roleId'); diff --git a/game-server/app/services/checkParam.ts b/game-server/app/services/checkParam.ts index 4b25eb233..e3c39efd8 100644 --- a/game-server/app/services/checkParam.ts +++ b/game-server/app/services/checkParam.ts @@ -1689,6 +1689,11 @@ export function checkRouteParam(route: string, msg: any) { if (!checkNaturalNumbers(msg.id, msg.count)) return false; break; } + case "role.equipHandler.composeStoneByItId": + { + if (!checkNaturalNumbers(msg.itId)) return false; + break; + } case "role.equipHandler.inheritJewel": { if (!checkNaturalNumbers(msg.originJewel, msg.targetJewel)) return false; diff --git a/game-server/app/services/role/checkMaterial.ts b/game-server/app/services/role/checkMaterial.ts index ed70cb5a7..a36b25cf7 100644 --- a/game-server/app/services/role/checkMaterial.ts +++ b/game-server/app/services/role/checkMaterial.ts @@ -1,4 +1,4 @@ -import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE } from '../../consts'; +import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE, CONSUME_TYPE, ITID_STONE_LIMIT } from '../../consts'; import { RoleModel, RoleType } from '../../db/Role'; import { ItemModel, ItemType } from '../../db/Item'; import { ItemInter, RewardInter, } from '../../pubUtils/interface'; @@ -210,4 +210,130 @@ export class CheckMeterial { public getConsume() { return this.consumes; } -} \ No newline at end of file +}; + +/** + * 获取升品所需消耗 + * @param id + * @returns + */ +export async function getComposeStoneNeedCost(id: number) { + let dicStone = gameData.stone.get(id); + if (!dicStone || dicStone.composeMaterial.length <= 0) return false; + return dicStone.composeMaterial; +} + +/** + * 获取当前类型6品以下玉石升级相关道具 + * @param roleId + * @param itId + * @returns + */ +export async function getCurItem(roleId: string, itId: number) { + //记录升品所需要的当前已有道具 + let curItem = new Map(); + let stoneLvId = new Map(); + let stoneItId = gameData.stoneItId.get(itId); + for (const { good_id, lv } of stoneItId) { + // stoneLvId.set(lv, good_id); + if (lv >= ITID_STONE_LIMIT) continue; + let nextLvMaterial = await getComposeStoneNeedCost(good_id); + if (!nextLvMaterial) continue; + for (let material of nextLvMaterial) { + if (curItem.get(material.id)) continue; + const item = await ItemModel.findbyRoleAndGid(roleId, material.id) + if (!item || item.count == 0) continue; + curItem.set(material.id, item.count); + } + } + + // console.log('---------------- curItem', curItem); + // console.log('---------------- stoneLvId', stoneLvId); + + return curItem; +} + +/** + * 计算玉石一键升品总产出与消耗 + * @param initialJewel + * @param curItem + * @returns + */ +export async function getComposeStoneCostAndAdd(curItem, itId) { + let allAddItem = new Map();//Array = [];//总产出 + let allCostItem = new Map();//Array = [];//总消耗 + + //计算升品所需消耗 + for (let lv = ITID_STONE_LIMIT - 1; lv >= 1; lv--) { + for (let indexLv = lv; indexLv < ITID_STONE_LIMIT; indexLv++) { + + let id = gameData.stoneItIdLv.get(`${itId}_${indexLv}`); + // console.log("------- id", id); + let tempItem1 = curItem.get(id) ? curItem.get(id) : 0; + let tempItem2 = allAddItem.get(id) ? allAddItem.get(id) : 0 + let count = tempItem1 + tempItem2; + if (count == 0) continue;//当前品没有,无法进行升下一品 + + let nextLvId = gameData.stoneItIdLv.get(`${itId}_${indexLv + 1}`); //stoneLvId.get(indexLv + 1); + // console.log("------- nextLvId", nextLvId); + + if (!nextLvId) continue; //不存在下一品 + + // console.log("-x-x-x-x-x-x-x--x-x- nextLvId", nextLvId) + //计算升到下一阶消耗 + let nextLvMaterial = await getComposeStoneNeedCost(nextLvId); + // console.log("x-x-x-x-x--x-x-x-x-x-x-- nextLvMaterial", nextLvMaterial) + if (!nextLvMaterial || nextLvMaterial.length == 0) { + //升下一品不存在消耗 + //产出 + let addCount = allAddItem.get(nextLvId) ? allAddItem.get(nextLvId) : 0 + allAddItem.set(nextLvId, addCount + count); + + continue; + } + + // 计算能升品的下一品新增数量 + let nextLvCount = nextLvMaterial[0].count ? nextLvMaterial[0].count : 0; + for (let material of nextLvMaterial) { + let tempCount1 = curItem.get(material.id) ? curItem.get(material.id) : 0; + let tempCount2 = allAddItem.get(material.id) ? allAddItem.get(material.id) : 0; + nextLvCount = Math.min(nextLvCount, Math.floor((tempCount1 + tempCount2) / material.count)); + } + console.log("x-x--x-x-x-x-x-x-x-x- nextLvCount", nextLvCount) + if (nextLvCount == 0) continue;// 不能升品 + + // 消耗 + for (let material of nextLvMaterial) { + let costCount = nextLvCount * material.count; + let tempCostCount = allCostItem.get(material.id) ? allCostItem.get(material.id) : 0; + allCostItem.set(material.id, tempCostCount + costCount); + + let tempCount1 = curItem.get(material.id); + let tempCount2 = allAddItem.get(material.id); + if (tempCount1) { + if (tempCount1 > costCount) { + curItem.set(material.id, tempCount1 - costCount); + continue; + } + + curItem.delete(material.id); + allAddItem.set(material.id, (tempCount2 - (costCount - tempCount1))); + continue; + } + allAddItem.set(material.id, tempCount2 - costCount); + } + + // 产出 + let addCount = allAddItem.get(nextLvId) ? allAddItem.get(nextLvId) : 0 + allAddItem.set(nextLvId, addCount + nextLvCount); + } + } + + // console.log('---------------- allCostItem', allCostItem); + // console.log('---------------- allAddItem', allAddItem); + + return { allCostItem, allAddItem }; +} + + + diff --git a/game-server/test/role.test.ts b/game-server/test/role.test.ts index 29ffa0ad0..425696390 100644 --- a/game-server/test/role.test.ts +++ b/game-server/test/role.test.ts @@ -88,4 +88,45 @@ describe('全局养成测试', function () { done(); }); }); -*/ \ No newline at end of file +*/ + +describe('玉石养成测试', function () { + let pinusClient: PinusWSClient; + let roleInfo; + + before(function (done) { + const c = new Client(); + const timer = setInterval(() => { + if (c.client) { + pinusClient = c.client; + roleInfo = c.roleInfo; + clearInterval(timer); + done(); + } + }, 500); + }); + + after(function (done) { + pinusClient.disconnect(); + // disconnect 后等待 500ms,供服务器清理环境、退出频道等 + setTimeout(() => { + done(); + }, 500); + }); + // { roleId: 'EAmqtKscfy', roleName: 'kYEXBWNk', serverId: 1, values: { reward: addItem } + it('宝石一键合成', function (done) { + // pinusClient.request('role.heroHandler.addItem', { id: 60001, count: 10 }, (res) => { + // console.log("--------------------添加道具", res) + // done(); + // }) + pinusClient.request('role.equipHandler.composeStoneByItId', { itId: 42 }, (res) => { + console.log("-------------------- res", res) + done(); + }) + }) +}); + +// function addItem() { +// let rewardInter; +// rewardInter.push({ id: 60001, count: 10 }); +// } \ No newline at end of file diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index a81196d6c..e8b9fcefe 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -30,6 +30,8 @@ export const CHECT_BATTLE_TYPE = 200; //非异常战斗类型 export const CHECT_BATTLE_TYPE_ATK_LIMIT = 201; // 我方武将最高攻小于地方最低防 export const CHECT_BATTLE_TYPE_HIDE = 202; // 隐藏武将 +export const ITID_STONE_LIMIT = 6; //玉石一键合成等级限制 + export enum TIME_OUTPUT_TYPE { DATE = 1, STAMP_10 = 2, diff --git a/shared/pubUtils/data.ts b/shared/pubUtils/data.ts index ea2595727..24c981b50 100644 --- a/shared/pubUtils/data.ts +++ b/shared/pubUtils/data.ts @@ -90,7 +90,7 @@ import { dicServerConst, loadServerConst } from './dictionary/DicServerConst'; const _ = require("underscore"); import { dicEquipById, dicEquipIdByJobClassAndEplace, loadEquip } from "./dictionary/DicEquip"; import { dicBlueprt, dicBlueprtByLv, dicJewel, loadJewel } from "./dictionary/DicJewel"; -import { dicStone, loadStone } from './dictionary/DicStone'; +import { dicStone, dicStoneItId, dicStoneItIdLv, loadStone } from './dictionary/DicStone'; import { dicEquipStrength, loadEquipStrength } from "./dictionary/DicEquipStrength"; import { dicEquipQuality, dicEquipQualityIdByEquipIdAndPoint, loadEquipQuality } from "./dictionary/DicEquipQuality"; import { dicEquipStar, dicEquipStarIdByEquipId, loadEquipStar } from './dictionary/DicEquipStar'; @@ -281,6 +281,8 @@ export const gameData = { equipIdByJobAndEPlace: dicEquipIdByJobClassAndEplace, jewel: dicJewel, stone: dicStone, + stoneItId: dicStoneItId, + stoneItIdLv: dicStoneItIdLv, equipStrengthenCost: dicEquipStrength, equipQuality: dicEquipQuality, equipQualityIdByEquipIdAndPoint: dicEquipQualityIdByEquipIdAndPoint, diff --git a/shared/pubUtils/dictionary/DicStone.ts b/shared/pubUtils/dictionary/DicStone.ts index 6f3a0a728..d083e6e90 100644 --- a/shared/pubUtils/dictionary/DicStone.ts +++ b/shared/pubUtils/dictionary/DicStone.ts @@ -10,8 +10,8 @@ export interface DicStone { readonly name: string; // 装备栏id readonly eplaceId: number; - // itid - readonly itid: number; + // itId + readonly itId: number; // 地玉石阶 readonly lv: number; // 地玉石品质 @@ -24,8 +24,12 @@ export interface DicStone { export const dicStone = new Map(); +export const dicStoneItId = new Map(); +export const dicStoneItIdLv = new Map(); export function loadStone() { dicStone.clear(); + dicStoneItId.clear(); + dicStoneItIdLv.clear(); let arr = readFileAndParse(FILENAME.DIC_STONE); @@ -33,6 +37,14 @@ export function loadStone() { o.composeMaterial = parseGoodStr(o.composeMaterial); o.attribute = parseAttr(o.attribute); dicStone.set(o.good_id, o); + + if (!dicStoneItId.has(o.itId)) { + dicStoneItId.set(o.itId, new Array()); + } + dicStoneItId.get(o.itId).push(o); + + + dicStoneItIdLv.set(`${o.itId}_${o.lv}`, o.good_id); }); arr = undefined; }