import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE } from '../../consts'; import { RoleModel, RoleType } from '../../db/Role'; import { ItemModel, ItemType } from '../../db/Item'; import { ItemInter, RewardInter, } from '../../pubUtils/interface'; import { gameData } from '../../pubUtils/data'; import { sortItems } from './util'; export class CheckMeterial { private roleId: string; private itemsIndb: Map = new Map(); // 玩家已有的东西 private notEnoughItems: Map = new Map(); // 缺少的数量 private consumes: ItemInter[] = []; // 消耗,正向数 private canReplace: boolean = false; // 是否可以被通用的啥代替代替 private tempConsumes: ItemInter[] = []; private goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD); private coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN); constructor(roleId: string, role?: RoleType, items?: ItemType[]) { this.roleId = roleId; if(role) { this.itemsIndb.set(this.goldId, role.gold); this.itemsIndb.set(this.coinId, role.coin); } if(items && items.length) { for(let {id, count} of items) { this.itemsIndb.set(id, count); } } } private pushToNotEnoughItems(id: number, count: number) { if(!this.notEnoughItems.has(id)) { this.notEnoughItems.set(id, 0); } this.notEnoughItems.set(id, this.notEnoughItems.get(id) + count); } private getNotEnoughItems() { let map = new Map(); for(let [ id, count ] of this.notEnoughItems) { map.set(id, count); } return map; } public async decrease(goods: {id: number, count: number}[]) { this.tempConsumes.splice(0, this.tempConsumes.length); this.notEnoughItems.clear(); let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST); for(let { id, count} of items) { console.log('#####', id, count) let notEnoughCount = await this.decreaseItem(id, count); console.log('##### notEnoughCount', id, notEnoughCount, this.canReplace) if(notEnoughCount > 0) { let isEnough = await this.checkReplaceItem(id, notEnoughCount); if(isEnough) { this.tempConsumes.push({ id, count: count - notEnoughCount }); } else { return false; } } } if(gold.length > 0) { let isEnough = await this.decreaseGold(gold); if(!isEnough) return false; } if(coin.length > 0) { let isEnough = await this.decreaseCoin(coin); if(!isEnough) return false; } this.consumes.push(...this.tempConsumes); return true; } public setCanReplace(canReplace: boolean) { this.canReplace = canReplace; } private async decreaseItem(id: number, count: number) { console.log('#### decreaseItem 1', id, count); if(!this.itemsIndb.has(id)) { let item = await ItemModel.findbyRoleAndGid(this.roleId, id); console.log('#### decreaseItem', item); if(!item) { this.pushToNotEnoughItems(id, count); return count; } this.itemsIndb.set(id, item.count); } if(this.itemsIndb.get(id) < count) { let notEnoughCount = count - this.itemsIndb.get(id); this.pushToNotEnoughItems(id, notEnoughCount); this.itemsIndb.set(id, 0); return notEnoughCount; } else { this.itemsIndb.set(id, this.itemsIndb.get(id) - count); this.tempConsumes.push({ id, count }); return 0 } } private async checkReplaceItem(id: number, count: number) { if(!this.canReplace) return false; let relationGoodId = gameData.relationGoods.get(id); if(!relationGoodId) return false; if(relationGoodId == this.goldId) { return await this.decreaseGold([{ count }]); } else if (relationGoodId == this.coinId) { return await this.decreaseCoin([count]); } else { let cnt = await this.decreaseItem(relationGoodId, count); return cnt == 0 } } private async decreaseGold(gold: { count: number }[]) { if(!this.itemsIndb.has(this.goldId)) { let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); this.itemsIndb.set(this.goldId, role.gold); this.itemsIndb.set(this.coinId, role.coin); } let goldCost = gold.reduce((pre, cur) => { return pre + cur.count }, 0); if(this.itemsIndb.get(this.goldId) < goldCost) { this.pushToNotEnoughItems(this.goldId, goldCost - this.itemsIndb.get(this.goldId)); this.itemsIndb.set(this.goldId, 0); return false; } this.itemsIndb.set(this.goldId, this.itemsIndb.get(this.goldId) - goldCost); this.tempConsumes.push({ id: this.goldId, count: goldCost }); return true } private async decreaseCoin(coin: number[]) { if(!this.itemsIndb.has(this.coinId)) { let role = await RoleModel.findByRoleId(this.roleId, 'gold coin'); this.itemsIndb.set(this.goldId, role.gold); this.itemsIndb.set(this.coinId, role.coin); } let coinCost = coin.reduce((pre, cur) => pre + cur, 0); if(this.itemsIndb.get(this.coinId) < coinCost) { this.pushToNotEnoughItems(this.coinId, coinCost - this.itemsIndb.get(this.coinId)); this.itemsIndb.set(this.coinId, 0); return false; } this.itemsIndb.set(this.coinId, this.itemsIndb.get(this.coinId) - coinCost); this.tempConsumes.push({ id: this.coinId, count: coinCost }); return true; } private getMaterialEnough(materials: RewardInter[], notEnoughItems: Map) { let newMaterials: RewardInter[] = []; for(let {id, count} of materials) { if(notEnoughItems.has(id)) { newMaterials.push({ id, count: count - notEnoughItems.get(id) }); } else { newMaterials.push({ id, count }); } } return newMaterials; } // 检查地玉石是否可以合成 public async composeStone(id: number, count: number) { let dicStone = gameData.stone.get(id); if(!dicStone || dicStone.composeMaterial.length <= 0) return false; // 1阶石头不能再从下合成返回不行 let materials = dicStone.composeMaterial.map(cur => ({...cur, count: cur.count * count })); let isEnough = await this.decrease(materials); if(!isEnough) { let notEnoughItems = this.getNotEnoughItems(); let newMaterials = this.getMaterialEnough(materials, notEnoughItems); let isEnough = await this.decrease(newMaterials); // 消耗掉除了不足的部分以外的其他部分 if(!isEnough) return false; let isAllOK = true; // 如果有石头不足,向下补充,isAllOK标识不足的都能补充上 for(let [id, count] of notEnoughItems) { let isEnough = await this.composeStone(id, count); if(!isEnough) { isAllOK = false; break; } } return isAllOK; } else { return true; } } public getConsume() { return this.consumes; } }