136 lines
5.5 KiB
TypeScript
136 lines
5.5 KiB
TypeScript
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<number, number> = new Map(); // 玩家已有的东西
|
||
private notEnoughItems: Map<number, number> = new Map(); // 缺少的数量
|
||
private consumes: 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<number, number>();
|
||
for(let [ id, count ] of this.notEnoughItems) {
|
||
map.set(id, count);
|
||
}
|
||
return map;
|
||
}
|
||
|
||
public async decrease(goods: {id: number, count: number}[]) {
|
||
this.notEnoughItems.clear();
|
||
let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
|
||
let isEnough = true;
|
||
for(let { id, count} of items) {
|
||
if(!this.itemsIndb.has(id)) {
|
||
let item = await ItemModel.findbyRoleAndGid(this.roleId, id);
|
||
if(!item) {
|
||
this.pushToNotEnoughItems(id, count);
|
||
isEnough = false; break;
|
||
}
|
||
this.itemsIndb.set(id, item.count);
|
||
}
|
||
if(this.itemsIndb.get(id) < count) {
|
||
this.pushToNotEnoughItems(id, count - this.itemsIndb.get(id));
|
||
isEnough = false; break;
|
||
}
|
||
this.itemsIndb.set(id, this.itemsIndb.get(id) - count);
|
||
}
|
||
|
||
if(gold.length > 0) {
|
||
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));
|
||
isEnough = false;
|
||
}
|
||
this.itemsIndb.set(this.goldId, this.itemsIndb.get(this.goldId) - goldCost);
|
||
}
|
||
if(isEnough && coin.length > 0) {
|
||
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));
|
||
isEnough = false;
|
||
}
|
||
this.itemsIndb.set(this.coinId, this.itemsIndb.get(this.coinId) - coinCost);
|
||
}
|
||
|
||
if(isEnough) this.consumes.push(...goods);
|
||
return isEnough;
|
||
}
|
||
|
||
private getMaterialEnough(materials: RewardInter[], notEnoughItems: Map<number, number>) {
|
||
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;
|
||
}
|
||
} |