需求:
- 对于穿戴中的装备,按照品质从低到高,依次提升品质。把较低品质的装备都提升到同一品质,然后再一起提升
- 对于背包内的道具,从最低阶开始合成,每次都把所有品质网上提一级,直到合成到顶级或者材料不够为止
思路:
先把合成涉及的材料的道具id找到,记录背包内道具数量。以key, value形式记录道具id,数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17/** 记录背包内合成所需道具的数量 */ private getBagSource(): Map<ItemId, number> { let bagList = new Map<ItemId, number>(); const bagModule = this.agent.getModule(ModuleNames.ModuleBag); const configM = ConfigMgr.instance.getConfig(ConfigFiles.configPetEquip); for (const cfg of configM.cfgs.values()) { if (cfg.totalEquipCost.length > 0) { for (const [itemId, v] of cfg.totalEquipCost) { const count = bagModule.getItemCountByItemId(BagId.PetEquip, itemId); if (count > 0) { bagList.set(itemId, count); } } } } return bagList; }一键合成顺序。按策划规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16private getInitEquipList(): Array<PetEquip> { let arr: Array<PetEquip> = []; let datas = this.toDb(); for (const data of datas[0]) { let copyEquip = new PetEquip(0); copyEquip.petEquipFromDb(data); arr.push(copyEquip); } arr.sort((a, b): number => { if (a.color == b.color) { return a.sType - b.sType; } return a.color - b.color; }); return arr; }合成,检查消耗。
实际拥有的道具数量 = 背包内数量bagList + 新生成的中间状态道具数量newList - 消耗的道具usedList。这里采取的是bfs,根据实际道具数量生成目标道具target所需要的消耗材料。比如合成一个道具a需要3个道具b,合成一个道具b需要3个道具c。假设背包里有1个道具b,10个道具c,那么根据已有道具生成道具a的消耗材料 = 1个道具b + 6个道具c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54//背包内资源数量 let bagList = this.getBagSource(); //消耗数量 let usedList = new Map<ItemId, number>(); //新生成数量 let newList = new Map<ItemId, number>(); /** * 根据背包内已有材料,生成合成目标道具id所需消耗 * @param targetItemId 要合成的目标道具id * @param bagList 背包里已有的道具数量 * @param usedList 已使用的道具数量 * @param newList 新增的道具数量 * @param speed 合成目标道具数量 * @param includeMainId 是否包含主武器id,穿戴中的装备作为材料 */ private findTargetCost( targetItemId: ItemId, bagList: Map<ItemId, number>, usedList: Map<ItemId, number>, newList: Map<ItemId, number>, speed: number, includeMainId: boolean): void { const configM = ConfigMgr.instance.getConfig(ConfigFiles.configPetEquip); const cfg = configM.cfgs.get(targetItemId); if (cfg) { let _cost = cfg.subCost; if (!includeMainId) { _cost = cfg.totalEquipCost; } //到底了,最低品质的材料 if (!_cost || _cost.length <= 0) { let tmp = usedList.get(cfg.itemId) || 0; usedList.set(cfg.itemId, tmp + speed); } for (const [itemId, count] of _cost) { const bagCount = bagList.get(itemId) || 0; const newCount = newList.get(itemId) || 0; const usedCount = usedList.get(itemId) || 0; const realCOunt = bagCount + newCount - usedCount; if (count * speed > realCOunt) { //缺少的道具 const num = count * speed - realCOunt; this.findTargetCost(itemId, bagList, usedList, newList, num, false); } else { let tmp = usedList.get(itemId) || 0; usedList.set(itemId, tmp + count * speed); } } } }检查消耗,消耗回滚。usedList是通过地址作为参数传递的,所以在进行合成之前需要深拷贝一份旧的消耗,如果道具不足,则回滚消耗,结束合成,否则继续。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21/** 检查消耗 */ private checkCost(bagList: Map<ItemId, number>, usedList: Map<ItemId, number>, newList: Map<ItemId, number>): boolean { for (const [itemId, count] of usedList) { const bagCount = bagList.get(itemId) || 0; const newCount = newList.get(itemId) || 0; if (count > bagCount + newCount) { return false; } } return true; } let oldUsedList = new Map<ItemId, number>(usedList); this.findTargetCost(cfg.nextColorItemId, bagList, usedList, newList, 1, true); if (this.checkCost(bagList, usedList, newList)) { } else { //回滚 usedList = oldUsedList; }提升合成速度。让合成速率成指数级增长,减少接口执行时间
1 2 3 4 5 6 7 8 9/** 根据上一次合成调整合成速度 */ private genComposeSpeed(curSpeed: number, lastResult: ErrorCode): number { if (lastResult == ErrorCode.Ok) { return curSpeed * 2; } else { return Math.floor(curSpeed / 2); } }