init
This commit is contained in:
@@ -1,423 +1,423 @@
|
||||
import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE, CONSUME_TYPE, ITID_STONE_LIMIT, HERO_GROW_MAX, ABI_STAGE } from '../../consts';
|
||||
import { RoleModel, RoleType } from '../../db/Role';
|
||||
import { ItemModel, ItemType } from '../../db/Item';
|
||||
import { ItemInter, RewardInter, } from '../../pubUtils/interface';
|
||||
import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from '../../pubUtils/data';
|
||||
import { sortItems } from './util';
|
||||
import { HeroType } from '../../db/Hero';
|
||||
|
||||
|
||||
export class CheckMeterial {
|
||||
private roleId: string;
|
||||
private itemsIndb: Map<number, number> = new Map(); // 玩家已有的东西
|
||||
private notEnoughItems: Map<number, number> = 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);
|
||||
}
|
||||
|
||||
public 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.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) {
|
||||
let notEnoughCount = await this.decreaseItem(id, count);
|
||||
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 async decreaseItemsContinue(goods: { id: number, count: number }[]) {
|
||||
this.tempConsumes.splice(0, this.tempConsumes.length);
|
||||
this.notEnoughItems.clear();
|
||||
let { items } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
|
||||
let itemIsEnough = true;
|
||||
for (let { id, count } of items) {
|
||||
let notEnoughCount = await this.decreaseItem(id, count);
|
||||
if (notEnoughCount > 0) {
|
||||
let isEnough = await this.checkReplaceItem(id, notEnoughCount);
|
||||
if (isEnough) {
|
||||
this.tempConsumes.push({ id, count: count - notEnoughCount });
|
||||
} else {
|
||||
itemIsEnough = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.consumes.push(...this.tempConsumes);
|
||||
return itemIsEnough;
|
||||
}
|
||||
|
||||
public setCanReplace(canReplace: boolean) {
|
||||
this.canReplace = canReplace;
|
||||
}
|
||||
|
||||
private async decreaseItem(id: number, count: number) {
|
||||
if (!this.itemsIndb.has(id)) {
|
||||
let item = await ItemModel.findbyRoleAndGid(this.roleId, id);
|
||||
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<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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取升品所需消耗
|
||||
* @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 {string} roleId
|
||||
* @param {number} itId
|
||||
* @returns
|
||||
*/
|
||||
export async function getCurItem(roleId: string, itId: number) {
|
||||
let curItem = new Map<number, number>();
|
||||
let stoneItId = gameData.stoneItId.get(itId);
|
||||
let goodIds = [];
|
||||
for (const { good_id, lv } of stoneItId) {
|
||||
if (lv > ITID_STONE_LIMIT) continue;
|
||||
let nextLvMaterial = await getComposeStoneNeedCost(good_id);
|
||||
if (!nextLvMaterial) continue;
|
||||
for (let material of nextLvMaterial) {
|
||||
goodIds.push(material.id);
|
||||
}
|
||||
}
|
||||
|
||||
let items = await ItemModel.find({ roleId, id: { $in: goodIds } });
|
||||
if (!items || items.length == 0) return curItem;
|
||||
for (let { id, count } of items) {
|
||||
if (count == 0) continue;
|
||||
curItem.set(id, count);
|
||||
}
|
||||
return curItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算玉石一键升品总产出与消耗
|
||||
* @param initialJewel
|
||||
* @param curItem
|
||||
* @returns
|
||||
*/
|
||||
export async function getComposeStoneCostAndAdd(curItem, itId) {
|
||||
let allAddItem = new Map<number, number>();
|
||||
let allCostItem = new Map<number, number>();
|
||||
|
||||
//计算升品所需消耗
|
||||
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}`);
|
||||
let tempItem1 = curItem.get(id) || 0;
|
||||
let tempItem2 = allAddItem.get(id) || 0
|
||||
let count = tempItem1 + tempItem2;
|
||||
if (count == 0) continue;//当前品没有,无法进行升下一品
|
||||
|
||||
let nextLvId = gameData.stoneItIdLv.get(`${itId}_${indexLv + 1}`);
|
||||
if (!nextLvId) continue; //不存在下一品
|
||||
|
||||
//计算升到下一阶消耗
|
||||
let nextLvMaterial = await getComposeStoneNeedCost(nextLvId);
|
||||
if (!nextLvMaterial || nextLvMaterial.length == 0) {
|
||||
//升下一品不存在消耗
|
||||
//产出
|
||||
let addCount = allAddItem.get(nextLvId) || 0
|
||||
allAddItem.set(nextLvId, addCount + count);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算能升品的下一品新增数量
|
||||
//设置初始数量
|
||||
let initial = nextLvMaterial[0];
|
||||
if (!initial.count || initial.count == 0) {
|
||||
console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId);
|
||||
continue;
|
||||
}
|
||||
let val1 = curItem.get(initial.id) || 0;
|
||||
let val2 = allAddItem.get(initial.id) || 0;
|
||||
let nextLvCount = Math.floor((val1 + val2) / initial.count);//设置初始值
|
||||
|
||||
for (let material of nextLvMaterial) {
|
||||
if (!material.count || material.count == 0) {
|
||||
nextLvCount = 0;
|
||||
console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId);
|
||||
continue;
|
||||
}
|
||||
let tempCount1 = curItem.get(material.id) || 0;
|
||||
let tempCount2 = allAddItem.get(material.id) || 0;
|
||||
nextLvCount = Math.min(nextLvCount, Math.floor((tempCount1 + tempCount2) / material.count));
|
||||
}
|
||||
|
||||
if (nextLvCount == 0) {
|
||||
// console.log('---------------- curItem', curItem);
|
||||
// console.log('---------------- indexLv', indexLv);
|
||||
// console.log('---------------- nextLvCount', nextLvCount);
|
||||
// console.log('---------------- allCostItem', allCostItem);
|
||||
// console.log('---------------- allAddItem', allAddItem);
|
||||
continue;// 不能升品
|
||||
}
|
||||
|
||||
// 消耗
|
||||
for (let material of nextLvMaterial) {
|
||||
let needCostCount = nextLvCount * material.count; //需要消耗数量
|
||||
let tempCount1 = curItem.get(material.id) || 0; // 当前item中已有的数量
|
||||
let tempCount2 = allAddItem.get(material.id) || 0; // 当前总产出中已有的数量
|
||||
let tempCostCount = allCostItem.get(material.id) || 0; // 当前总消耗中已有的数量
|
||||
|
||||
let diff = tempCount1 - needCostCount;
|
||||
if (diff > 0) {// 先消耗item中的
|
||||
curItem.set(material.id, diff);
|
||||
allCostItem.set(material.id, tempCostCount + needCostCount); //记录入总消耗(仅item中,allAddItem消耗会在其中减掉)
|
||||
continue;
|
||||
}
|
||||
|
||||
curItem.delete(material.id);
|
||||
if (tempCount1 != 0) allCostItem.set(material.id, tempCostCount + tempCount1);//记录入总消耗(0不记录)
|
||||
|
||||
|
||||
if (tempCount2 - Math.abs(diff) < 0) return;//异常
|
||||
|
||||
allAddItem.set(material.id, (tempCount2 - Math.abs(diff)));
|
||||
}
|
||||
|
||||
// 产出
|
||||
let addCount = allAddItem.get(nextLvId) || 0
|
||||
allAddItem.set(nextLvId, addCount + nextLvCount);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('---------------- allCostItem', allCostItem);
|
||||
// console.log('---------------- allAddItem', allAddItem);
|
||||
|
||||
return { allCostItem, allAddItem };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 计算升到6彩后剩余碎片
|
||||
* @param roleId
|
||||
* @param hid
|
||||
* @returns
|
||||
*/
|
||||
export async function calUpSixColorsResidueFragment(roleId: string, hero: HeroType, hid: number, count?: number) {
|
||||
let needFragment = 0;
|
||||
|
||||
let dicHero = gameData.hero.get(hid);
|
||||
if (!dicHero) return;
|
||||
let { pieceId, jobid } = dicHero;
|
||||
|
||||
let dicJob = gameData.job.get(jobid);
|
||||
if (!dicJob) return;
|
||||
|
||||
let curItemCount = count;
|
||||
if (!count) {
|
||||
let item = await ItemModel.findbyRoleAndGid(roleId, pieceId);
|
||||
curItemCount = item?.count || 0;
|
||||
}
|
||||
if (curItemCount < 0) return;
|
||||
|
||||
let { star: oldStar, starStage: oldStarStage, quality: oldQuality, colorStar: oldColorStar, colorStarStage: oldColorStarStage, } = hero;
|
||||
|
||||
// 计算升星
|
||||
if (oldStar < HERO_GROW_MAX.STAR) {
|
||||
for (let starIndex = oldStar; starIndex < HERO_GROW_MAX.STAR; starIndex++) {
|
||||
const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, oldQuality, starIndex);
|
||||
if (starIndex == oldStar) {
|
||||
needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * (ABI_STAGE.END - oldStarStage);
|
||||
continue;
|
||||
}
|
||||
needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * ABI_STAGE.END;
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
// 计算升品
|
||||
if (oldQuality < HERO_GROW_MAX.QUALITY) {
|
||||
for (let qualityIndex = oldQuality; qualityIndex < HERO_GROW_MAX.QUALITY; qualityIndex++) {
|
||||
const curDicHeroQualityUp = gameData.heroQualityUp.get(qualityIndex);
|
||||
needFragment += curDicHeroQualityUp?.fragmentNum || 0;
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
// 计算觉醒升6彩
|
||||
if (oldColorStar < HERO_GROW_MAX.COLORSTAR) {
|
||||
for (let colorStarIndex = oldColorStar; colorStarIndex < 6; colorStarIndex++) {
|
||||
const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, colorStarIndex)
|
||||
if (colorStarIndex == 0) {
|
||||
needFragment += curDicHeroStar?.fragmentNum || 0;
|
||||
continue;
|
||||
}
|
||||
if (colorStarIndex == oldColorStar) {
|
||||
needFragment += (curDicHeroStar?.fragmentNum || 0) * (ABI_STAGE.END - oldColorStarStage);
|
||||
continue;
|
||||
}
|
||||
needFragment += (curDicHeroStar?.fragmentNum || 0) * ABI_STAGE.END;
|
||||
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
|
||||
return curItemCount - needFragment;
|
||||
}
|
||||
import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE, CONSUME_TYPE, ITID_STONE_LIMIT, HERO_GROW_MAX, ABI_STAGE } from '@consts';
|
||||
import { RoleModel, RoleType } from '@db/Role';
|
||||
import { ItemModel, ItemType } from '@db/Item';
|
||||
import { ItemInter, RewardInter, } from '@pubUtils/interface';
|
||||
import { gameData, getHeroStarByQuality, getHeroWakeByQuality } from '@pubUtils/data';
|
||||
import { sortItems } from './util';
|
||||
import { HeroType } from '@db/Hero';
|
||||
|
||||
|
||||
export class CheckMeterial {
|
||||
private roleId: string;
|
||||
private itemsIndb: Map<number, number> = new Map(); // 玩家已有的东西
|
||||
private notEnoughItems: Map<number, number> = 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);
|
||||
}
|
||||
|
||||
public 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.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) {
|
||||
let notEnoughCount = await this.decreaseItem(id, count);
|
||||
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 async decreaseItemsContinue(goods: { id: number, count: number }[]) {
|
||||
this.tempConsumes.splice(0, this.tempConsumes.length);
|
||||
this.notEnoughItems.clear();
|
||||
let { items } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
|
||||
let itemIsEnough = true;
|
||||
for (let { id, count } of items) {
|
||||
let notEnoughCount = await this.decreaseItem(id, count);
|
||||
if (notEnoughCount > 0) {
|
||||
let isEnough = await this.checkReplaceItem(id, notEnoughCount);
|
||||
if (isEnough) {
|
||||
this.tempConsumes.push({ id, count: count - notEnoughCount });
|
||||
} else {
|
||||
itemIsEnough = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.consumes.push(...this.tempConsumes);
|
||||
return itemIsEnough;
|
||||
}
|
||||
|
||||
public setCanReplace(canReplace: boolean) {
|
||||
this.canReplace = canReplace;
|
||||
}
|
||||
|
||||
private async decreaseItem(id: number, count: number) {
|
||||
if (!this.itemsIndb.has(id)) {
|
||||
let item = await ItemModel.findbyRoleAndGid(this.roleId, id);
|
||||
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<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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取升品所需消耗
|
||||
* @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 {string} roleId
|
||||
* @param {number} itId
|
||||
* @returns
|
||||
*/
|
||||
export async function getCurItem(roleId: string, itId: number) {
|
||||
let curItem = new Map<number, number>();
|
||||
let stoneItId = gameData.stoneItId.get(itId);
|
||||
let goodIds = [];
|
||||
for (const { good_id, lv } of stoneItId) {
|
||||
if (lv > ITID_STONE_LIMIT) continue;
|
||||
let nextLvMaterial = await getComposeStoneNeedCost(good_id);
|
||||
if (!nextLvMaterial) continue;
|
||||
for (let material of nextLvMaterial) {
|
||||
goodIds.push(material.id);
|
||||
}
|
||||
}
|
||||
|
||||
let items = await ItemModel.find({ roleId, id: { $in: goodIds } });
|
||||
if (!items || items.length == 0) return curItem;
|
||||
for (let { id, count } of items) {
|
||||
if (count == 0) continue;
|
||||
curItem.set(id, count);
|
||||
}
|
||||
return curItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算玉石一键升品总产出与消耗
|
||||
* @param initialJewel
|
||||
* @param curItem
|
||||
* @returns
|
||||
*/
|
||||
export async function getComposeStoneCostAndAdd(curItem, itId) {
|
||||
let allAddItem = new Map<number, number>();
|
||||
let allCostItem = new Map<number, number>();
|
||||
|
||||
//计算升品所需消耗
|
||||
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}`);
|
||||
let tempItem1 = curItem.get(id) || 0;
|
||||
let tempItem2 = allAddItem.get(id) || 0
|
||||
let count = tempItem1 + tempItem2;
|
||||
if (count == 0) continue;//当前品没有,无法进行升下一品
|
||||
|
||||
let nextLvId = gameData.stoneItIdLv.get(`${itId}_${indexLv + 1}`);
|
||||
if (!nextLvId) continue; //不存在下一品
|
||||
|
||||
//计算升到下一阶消耗
|
||||
let nextLvMaterial = await getComposeStoneNeedCost(nextLvId);
|
||||
if (!nextLvMaterial || nextLvMaterial.length == 0) {
|
||||
//升下一品不存在消耗
|
||||
//产出
|
||||
let addCount = allAddItem.get(nextLvId) || 0
|
||||
allAddItem.set(nextLvId, addCount + count);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算能升品的下一品新增数量
|
||||
//设置初始数量
|
||||
let initial = nextLvMaterial[0];
|
||||
if (!initial.count || initial.count == 0) {
|
||||
console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId);
|
||||
continue;
|
||||
}
|
||||
let val1 = curItem.get(initial.id) || 0;
|
||||
let val2 = allAddItem.get(initial.id) || 0;
|
||||
let nextLvCount = Math.floor((val1 + val2) / initial.count);//设置初始值
|
||||
|
||||
for (let material of nextLvMaterial) {
|
||||
if (!material.count || material.count == 0) {
|
||||
nextLvCount = 0;
|
||||
console.error("dic_zyz_stone配置错误, good_id=%s", nextLvId);
|
||||
continue;
|
||||
}
|
||||
let tempCount1 = curItem.get(material.id) || 0;
|
||||
let tempCount2 = allAddItem.get(material.id) || 0;
|
||||
nextLvCount = Math.min(nextLvCount, Math.floor((tempCount1 + tempCount2) / material.count));
|
||||
}
|
||||
|
||||
if (nextLvCount == 0) {
|
||||
// console.log('---------------- curItem', curItem);
|
||||
// console.log('---------------- indexLv', indexLv);
|
||||
// console.log('---------------- nextLvCount', nextLvCount);
|
||||
// console.log('---------------- allCostItem', allCostItem);
|
||||
// console.log('---------------- allAddItem', allAddItem);
|
||||
continue;// 不能升品
|
||||
}
|
||||
|
||||
// 消耗
|
||||
for (let material of nextLvMaterial) {
|
||||
let needCostCount = nextLvCount * material.count; //需要消耗数量
|
||||
let tempCount1 = curItem.get(material.id) || 0; // 当前item中已有的数量
|
||||
let tempCount2 = allAddItem.get(material.id) || 0; // 当前总产出中已有的数量
|
||||
let tempCostCount = allCostItem.get(material.id) || 0; // 当前总消耗中已有的数量
|
||||
|
||||
let diff = tempCount1 - needCostCount;
|
||||
if (diff > 0) {// 先消耗item中的
|
||||
curItem.set(material.id, diff);
|
||||
allCostItem.set(material.id, tempCostCount + needCostCount); //记录入总消耗(仅item中,allAddItem消耗会在其中减掉)
|
||||
continue;
|
||||
}
|
||||
|
||||
curItem.delete(material.id);
|
||||
if (tempCount1 != 0) allCostItem.set(material.id, tempCostCount + tempCount1);//记录入总消耗(0不记录)
|
||||
|
||||
|
||||
if (tempCount2 - Math.abs(diff) < 0) return;//异常
|
||||
|
||||
allAddItem.set(material.id, (tempCount2 - Math.abs(diff)));
|
||||
}
|
||||
|
||||
// 产出
|
||||
let addCount = allAddItem.get(nextLvId) || 0
|
||||
allAddItem.set(nextLvId, addCount + nextLvCount);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('---------------- allCostItem', allCostItem);
|
||||
// console.log('---------------- allAddItem', allAddItem);
|
||||
|
||||
return { allCostItem, allAddItem };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 计算升到6彩后剩余碎片
|
||||
* @param roleId
|
||||
* @param hid
|
||||
* @returns
|
||||
*/
|
||||
export async function calUpSixColorsResidueFragment(roleId: string, hero: HeroType, hid: number, count?: number) {
|
||||
let needFragment = 0;
|
||||
|
||||
let dicHero = gameData.hero.get(hid);
|
||||
if (!dicHero) return;
|
||||
let { pieceId, jobid } = dicHero;
|
||||
|
||||
let dicJob = gameData.job.get(jobid);
|
||||
if (!dicJob) return;
|
||||
|
||||
let curItemCount = count;
|
||||
if (!count) {
|
||||
let item = await ItemModel.findbyRoleAndGid(roleId, pieceId);
|
||||
curItemCount = item?.count || 0;
|
||||
}
|
||||
if (curItemCount < 0) return;
|
||||
|
||||
let { star: oldStar, starStage: oldStarStage, quality: oldQuality, colorStar: oldColorStar, colorStarStage: oldColorStarStage, } = hero;
|
||||
|
||||
// 计算升星
|
||||
if (oldStar < HERO_GROW_MAX.STAR) {
|
||||
for (let starIndex = oldStar; starIndex < HERO_GROW_MAX.STAR; starIndex++) {
|
||||
const curDicHeroStar = getHeroStarByQuality(dicJob.job_class, oldQuality, starIndex);
|
||||
if (starIndex == oldStar) {
|
||||
needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * (ABI_STAGE.END - oldStarStage);
|
||||
continue;
|
||||
}
|
||||
needFragment += (curDicHeroStar?.advanceUpFragmentNum || 0) * ABI_STAGE.END;
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
// 计算升品
|
||||
if (oldQuality < HERO_GROW_MAX.QUALITY) {
|
||||
for (let qualityIndex = oldQuality; qualityIndex < HERO_GROW_MAX.QUALITY; qualityIndex++) {
|
||||
const curDicHeroQualityUp = gameData.heroQualityUp.get(qualityIndex);
|
||||
needFragment += curDicHeroQualityUp?.fragmentNum || 0;
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
// 计算觉醒升6彩
|
||||
if (oldColorStar < HERO_GROW_MAX.COLORSTAR) {
|
||||
for (let colorStarIndex = oldColorStar; colorStarIndex < 6; colorStarIndex++) {
|
||||
const curDicHeroStar = getHeroWakeByQuality(dicJob.job_class, dicHero.quality, colorStarIndex)
|
||||
if (colorStarIndex == 0) {
|
||||
needFragment += curDicHeroStar?.fragmentNum || 0;
|
||||
continue;
|
||||
}
|
||||
if (colorStarIndex == oldColorStar) {
|
||||
needFragment += (curDicHeroStar?.fragmentNum || 0) * (ABI_STAGE.END - oldColorStarStage);
|
||||
continue;
|
||||
}
|
||||
needFragment += (curDicHeroStar?.fragmentNum || 0) * ABI_STAGE.END;
|
||||
|
||||
}
|
||||
}
|
||||
if (curItemCount < needFragment) return;
|
||||
|
||||
|
||||
return curItemCount - needFragment;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user