diff --git a/game-server/app/servers/role/handler/equipHandler.ts b/game-server/app/servers/role/handler/equipHandler.ts index 2f9286407..8102f72f2 100644 --- a/game-server/app/servers/role/handler/equipHandler.ts +++ b/game-server/app/servers/role/handler/equipHandler.ts @@ -7,6 +7,7 @@ import { addItems, handleCost } from "../../../services/rewardService"; import { checkMaterialEnough } from "../../../services/equipService"; import { EquipModel, RandSe } from "../../../db/Equip"; import { HeroModel, EPlace } from "../../../db/Hero"; +import { ItemModel } from "../../../db/Item"; import Role from "../../../db/Role"; import { calPlayerCeAndSave } from "../../../services/playerCeService"; import { getHeroJob, getGoodById, gameData, getJewelById, getHeroEquipByClassId } from "../../../pubUtils/data"; @@ -525,13 +526,18 @@ export class EquipHandler { if (good.type != CONSUME_TYPE.JEWEL) return resResult(STATUS.WRONG_PARMS); //检查宝石消耗是否合法TODO - consumes.concat(purchaseGoods) - let needConsumes = checkMaterialEnough(consumes, jewel, count); + if (!purchaseGoods) + purchaseGoods = []; + let needConsumes = checkMaterialEnough(consumes.concat(purchaseGoods), jewel, count); if (!needConsumes) - return resResult(STATUS.WRONG_PARMS); - await addItems(roleId, roleName, sid, purchaseGoods); - let res = await handleCost(roleId, sid, needConsumes); - if (!res) + 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 ItemModel.decreaseItems(roleId, items); + if (!!hasError) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); await addItems(roleId, roleName, sid, [{ id: jewel, count: count }]); return resResult(STATUS.SUCCESS); @@ -548,4 +554,44 @@ export class EquipHandler { } return resResult(STATUS.SUCCESS); } + //合成下一级宝石(装备镶嵌界面) + 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 goodInfo = getGoodById(jewel); + let good = ITID.get(goodInfo.itid); + let needUpdate = false; + let consumes: Array<{id: number, count: number, ratio?: number}> = []; + if (good.type != CONSUME_TYPE.JEWEL) + return resResult(STATUS.WRONG_PARMS); + let equip; + if (!!eid) { + equip = await EquipModel.getEquip(eid); + let index = _.findIndex(equip.holes,{id}); + if (index) { + equip.holes[id].jewel = jewel; + needUpdate = true; + consumes.push({id:jewel, count: 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 ItemModel.decreaseItems(roleId, consumes); + if (!!hasError) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + let res = await handleCost(roleId, sid, consumes); + if (!res) + return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); + let result = {}; + if (needUpdate) { + await EquipModel.updateEquipInfo(eid, { holes: equip.holes }); + } else { + result = await addItems(roleId, roleName, sid, [{ id: jewel, count: count }]); + } + return resResult(STATUS.SUCCESS, { goods: result }); + } } \ No newline at end of file diff --git a/game-server/app/servers/role/handler/heroHandler.ts b/game-server/app/servers/role/handler/heroHandler.ts index f44214ed0..52b60462f 100644 --- a/game-server/app/servers/role/handler/heroHandler.ts +++ b/game-server/app/servers/role/handler/heroHandler.ts @@ -21,14 +21,14 @@ export class HeroHandler { private channelService: ChannelService = this.app.get('channelService'); - public async test(msg: { id: number, count: number, seqId:number, type:number}, session: BackendSession) { + public async test(msg: { items:Array<{id: number, count: number, seqId:number, type:number}>}, session: BackendSession) { let roleId: string = session.get('roleId'); let roleName: string = session.get('roleName'); let sid: string = session.get('sid'); - let {id, count, seqId, type} = msg; + let {items} = msg; - let result = await handleCost(roleId, sid, [{id, count, seqId, type}] ); + let result = await handleCost(roleId, sid, items ); //let result = await addItems(roleId, roleName, sid, [{id, count}] ); if(!result) { return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH); diff --git a/game-server/app/services/equipService.ts b/game-server/app/services/equipService.ts index 39ef07c34..390f321d5 100644 --- a/game-server/app/services/equipService.ts +++ b/game-server/app/services/equipService.ts @@ -14,22 +14,30 @@ import { gameData, getJewelById } from '../pubUtils/data'; const _ = require('underscore'); export function checkMaterialEnough(consumes:Array<{id: number, count: number}>, jewel: number, jewelCount: number) { - consumes = mergeSameGoods(consumes); let comJewelMap = {}; + consumes = mergeSameGoods(consumes); let needConsumes: Array<{id: number, count: number}> = []; + let gidJewelInfo = getGoodById(jewel); for (let { id, count } of consumes) { let jewelInfo = getJewelById(id); - if (!jewelInfo) + if (!jewelInfo || !jewelInfo.count) continue; - let comcount = Math.floor((count + (comJewelMap[jewelInfo.good_id] || 0)) / jewelInfo.count); - if (comcount < 1) { - return false; + needConsumes.push({ id, count}); + comJewelMap[jewelInfo.good_id] = count + (comJewelMap[jewelInfo.good_id] || 0); + for (let i = jewelInfo.lvLimited; i < gidJewelInfo.lvLimited; i++) { + if (((comJewelMap[jewelInfo.good_id] || 0) % jewelInfo.count != 0)) { + break; + } + let comcount = Math.floor(((comJewelMap[jewelInfo.good_id] || 0)) / jewelInfo.count); + if (comcount < 1) { + break; + } + comJewelMap[jewelInfo.nextJewelId] = comcount + (comJewelMap[jewelInfo.nextJewelId] || 0); + delete comJewelMap[jewelInfo.good_id]; + if (!!jewelInfo.specialCount) + needConsumes.push({ count: jewelInfo.specialCount, id: jewelInfo.nextSpecialId}); + jewelInfo = getJewelById(jewelInfo.nextJewelId); } - needConsumes.push({ id, count }); - if (!!jewelInfo.specialMaterial.ids.length) - needConsumes.push({ id: jewelInfo.specialMaterial.ids[0], count: jewelInfo.specialMaterial.count}); - delete comJewelMap[jewelInfo.good_id]; - comJewelMap[jewelInfo.nextJewelId] = comcount + (comJewelMap[jewelInfo.nextJewelId] || 0); } if (comJewelMap[jewel] != jewelCount || Object.keys(comJewelMap).length != 1) return false; diff --git a/shared/db/Item.ts b/shared/db/Item.ts index 705730495..8055264ac 100644 --- a/shared/db/Item.ts +++ b/shared/db/Item.ts @@ -1,84 +1,107 @@ import BaseModel from './BaseModel'; -import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; +import { index, getModelForClass, prop, DocumentType, modelOptions, mongoose } from '@typegoose/typegoose'; +import Transaction from "mongoose-transactions/src/main"; @index({ roleId: 1, id: 1 }) @index({ seqId: 1 }) -@modelOptions({schemaOptions: {id: false}}) +@modelOptions({ schemaOptions: { id: false } }) export default class Item extends BaseModel { - @prop({ required: true, default: '' }) - roleId: string; // 角色 id - @prop({ required: true, default: '' }) - roleName: string; // 角色名称 + @prop({ required: true, default: '' }) + roleId: string; // 角色 id + @prop({ required: true, default: '' }) + roleName: string; // 角色名称 - @prop({ required: true, default: '' }) - id: number; // 道具 id - @prop({ required: true, default: '' }) - type: number; // 道具类型 - @prop({ required: true, default: '' }) - itemName: string; // 道具名称 - @prop({ required: true, default: 0 }) - hid: number; // 将魂:武将id,其他:0 - @prop({ required: true }) - count: number; // 道具数量 + @prop({ required: true, default: '' }) + id: number; // 道具 id + @prop({ required: true, default: '' }) + type: number; // 道具类型 + @prop({ required: true, default: '' }) + itemName: string; // 道具名称 + @prop({ required: true, default: 0 }) + hid: number; // 将魂:武将id,其他:0 + @prop({ required: true }) + count: number; // 道具数量 - public static async findbyRole(roleId: string, lean = true) { - const items: ItemType[] = await ItemModel.find({ roleId }).select('id count type').lean(lean); - return items; - } - - public static async findbyRoleAndIds(roleId: string, ids: Array, lean = true) { - const items: ItemType[] = await ItemModel.find({ roleId, id: {$in: ids} }).select('id count type').lean(lean); - return items; - } - - public static async findByRoleAndType(roleId: string, type: number, lean = true) { - const items: ItemType[] = await ItemModel.find({ roleId, type }).select('id count type').sort({id: 1}).lean(lean); - return items; - } - - public static async findbyRoleAndGidAndCount(roleId: string, id: number, count: number, lean = true) { - const items: ItemType = await ItemModel.findOne({ roleId, id, count: {$gte: count} }).select('id count type').lean(lean); - return items; - } - - public static async increaseItem(roleId: string, id: number, count: number, itemInfo: {roleId: string, roleName: string, id: number, itemName: string, type: number, hid?: number }, lean = true) { - const doc = new ItemModel(); - const setOnInsert = Object.assign(doc.toJSON(), itemInfo); - const items: ItemType = await ItemModel.findOneAndUpdate({roleId, id },{$setOnInsert: setOnInsert, $inc: { count }}, {new: true, upsert: true}).lean(lean); - return items; - } - - public static async decreaseItems(roleId: string, items: Array<{id: number, count: number}>, lean = true) { - let updateItems = new Array<{id: number, count: number}>(), hasError: boolean = false, result = new Array(); - for(let {id, count} of items) { - const rec: ItemType = await ItemModel.findOneAndUpdate({roleId, id, count: {$gte: count} },{ $inc: { count: -1 * count }}, {new: true}).lean(lean); - if(rec) { - result.push({id: rec.id, count: rec.count}); - updateItems.push({id, count}); - } else { - hasError = true; break; - } + public static async findbyRole(roleId: string, lean = true) { + const items: ItemType[] = await ItemModel.find({ roleId }).select('id count type').lean(lean); + return items; } - if(hasError) { // 数量不足 - for(let {id, count} of updateItems) { - await ItemModel.findOneAndUpdate({roleId, id },{ $inc: { count }}, {new: true}).lean(lean); - } - return {hasError: true} - } else { - return {hasError: false, result} - } - } - public static async deleteAccount(roleId: string) { - let result = await ItemModel.deleteMany({roleId}); - return result; - } - + public static async findbyRoleAndIds(roleId: string, ids: Array, lean = true) { + const items: ItemType[] = await ItemModel.find({ roleId, id: { $in: ids } }).select('id count type').lean(lean); + return items; + } + + public static async findByRoleAndType(roleId: string, type: number, lean = true) { + const items: ItemType[] = await ItemModel.find({ roleId, type }).select('id count type').sort({ id: 1 }).lean(lean); + return items; + } + + public static async findbyRoleAndGidAndCount(roleId: string, id: number, count: number, lean = true) { + const items: ItemType = await ItemModel.findOne({ roleId, id, count: { $gte: count } }).select('id count type').lean(lean); + return items; + } + + public static async increaseItem(roleId: string, id: number, count: number, itemInfo: { roleId: string, roleName: string, id: number, itemName: string, type: number, hid?: number }, lean = true) { + const doc = new ItemModel(); + const setOnInsert = Object.assign(doc.toJSON(), itemInfo); + const items: ItemType = await ItemModel.findOneAndUpdate({ roleId, id }, { $setOnInsert: setOnInsert, $inc: { count } }, { new: true, upsert: true }).lean(lean); + return items; + } + + public static async decreaseItems(roleId: string, items: Array<{id: number, count: number, ratio?: number}>, lean = true) { + let updateItems = new Array<{id: number, count: number}>(), hasError: boolean = false, result = new Array(); + for (let { id, count, ratio } of items) { + const rec: ItemType = await ItemModel.findOneAndUpdate({roleId, id, count: {$gte: count} },{ $inc: { count: -1 * count }}, {new: true}).lean(lean); + if(rec) { + result.push({id: rec.id, count: rec.count}); + updateItems.push({id, count}); + } else { + hasError = true; break; + } + } + if(hasError) { // 数量不足 + for(let {id, count} of updateItems) { + await ItemModel.findOneAndUpdate({roleId, id },{ $inc: { count }}, {new: true}).lean(lean); + } + return {hasError: true} + } else { + return {hasError: false, result} + } + } + // public static async decreaseItems(roleId: string, items: Array<{ id: number, count: number, ratio?: number}>, lean = true) { + // const transaction = new Transaction(); + // let hasError: boolean = false, result = new Array(); + // try { + // for (let { id, count, ratio } of items) { + // if (ratio) ratio = -1; + // await transaction.update({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}); + // //const rec: ItemType = await transaction.findOneAndUpdate({ roleId, id, count: { $gte: count } }, { $inc: { count: ratio * count } }, { new: true}).lean(lean); + // // if (!!rec) { + // // result.push({ id: rec.id, count: rec.count }); + // // } else { + // // hasError = true; break; + // // } + // } + // await transaction.run(); + // return {hasError, result}; + // } catch (error) { + // await transaction.rollback().catch(console.error); + // transaction.clean(); + // return {error}; + // } + // } + + public static async deleteAccount(roleId: string) { + let result = await ItemModel.deleteMany({ roleId }); + return result; + } } + export const ItemModel = getModelForClass(Item); -export interface ItemType extends Pick, keyof Item>{ - id: number; +export interface ItemType extends Pick, keyof Item> { + id: number; }; diff --git a/shared/pubUtils/dictionary/DicGoods.ts b/shared/pubUtils/dictionary/DicGoods.ts index 89c705ac0..6e31f8aa9 100644 --- a/shared/pubUtils/dictionary/DicGoods.ts +++ b/shared/pubUtils/dictionary/DicGoods.ts @@ -54,7 +54,8 @@ export interface DicGoods { readonly count?: number; readonly nextJewelId?: number; - + readonly specialCount?: number; + readonly nextSpecialId?: number; } const str = readJsonFile(FILENAME.DIC_GOODS); @@ -83,6 +84,8 @@ const DicGoodsKeys: KeysEnum = { pieceId: true, count: true, nextJewelId: true, + specialCount: true, + nextSpecialId: true } export const dicJewel = new Map(); export const dicGoods = new Map(); @@ -108,8 +111,14 @@ arr.forEach(o => { if (!!lastJewel) { lastJewel.count = material.count; lastJewel.nextJewelId = o.good_id; + if (!!o.specialMaterial.ids[0]) { + lastJewel.specialCount = o.specialMaterial.ids[0]; + lastJewel.nextSpecialId = o.specialMaterial.count; + } dicJewel.set(lastJewel.good_id, _.pick(lastJewel, Object.keys(DicGoodsKeys))); } + } else { + dicJewel.set(o.good_id, _.pick(o, Object.keys(DicGoodsKeys))); } } });