init
This commit is contained in:
+1508
-1508
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,103 +1,103 @@
|
||||
import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM, COUNTER, PUSH_ROUTE } from "../../consts";
|
||||
import { SkinModel } from "../../db/Skin";
|
||||
import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "../../db/Hero";
|
||||
import { SkinUpdate } from "../../db/Skin";
|
||||
import { nowSeconds } from "../../pubUtils/timeUtil";
|
||||
import { CreateHeroParam, HeroParam, HeroShowParam } from "../../domain/roleField/hero";
|
||||
import { ItemInter, RewardInter } from "../../pubUtils/interface";
|
||||
import { transPiece } from "./util";
|
||||
import { addItems, unlockFigure, } from "./rewardService";
|
||||
import { CounterModel } from "../../db/Counter";
|
||||
import { calculateCes } from "../playerCeService";
|
||||
import { RoleUpdate } from "../../db/Role";
|
||||
import { sendMessageToUserWithSuc } from "../pushService";
|
||||
import { checkTaskInCreateHero } from "../task/taskService";
|
||||
import { filterHeroes } from "../dataService";
|
||||
import { pushGetHero } from "../sysChatService";
|
||||
|
||||
/**
|
||||
* 创建多个武将
|
||||
* @param roleId
|
||||
* @param sid
|
||||
* @param serverId
|
||||
* @param heroInfo
|
||||
*/
|
||||
export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[], initRoleInfos?: RoleUpdate) {
|
||||
heroInfo = filterHeroes(heroInfo, obj => obj.hid, roleId);
|
||||
let hids = heroInfo.map(cur => cur.hid);
|
||||
let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId);
|
||||
|
||||
let createHeroeInfos: CreateHeroParam[] = [], pieces: ItemInter[] = [];
|
||||
for (let h of heroInfo) {
|
||||
let heroCount = h.count || 1;
|
||||
if (userHeroesMap.has(h.hid)) {
|
||||
let { pieceId, count } = transPiece(h.hid);
|
||||
pieces.push({ id: pieceId, count: count * heroCount });
|
||||
} else {
|
||||
createHeroeInfos.push(h);
|
||||
userHeroesMap.set(h.hid, null);
|
||||
if (heroCount > 1) {
|
||||
let { pieceId, count } = transPiece(h.hid);
|
||||
pieces.push({ id: pieceId, count: count * (heroCount - 1) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], showHeroes: HeroShowParam[] = [];
|
||||
let figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = [];
|
||||
let incHeroNum = 0;
|
||||
let skins: SkinUpdate[] = [];
|
||||
if (createHeroeInfos.length > 0) {
|
||||
let heroInfos = new Map<number, HeroUpdate>();
|
||||
for(let {hid, ...info} of createHeroeInfos) {
|
||||
let originSkins = await SkinModel.findbyRoleAndHid(roleId, hid);
|
||||
let initSkin = SkinModel.getInitInfo(hid);
|
||||
skins.push(initSkin); // 初始皮肤
|
||||
let seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
let initHeroSkins = [initSkin, ...originSkins].map((skin, index) => new HeroSkin(skin, index == 0));
|
||||
let initHero = HeroModel.getInitInfo(hid, { ...info, seqId, serverId, roleId, roleName, skins: initHeroSkins });
|
||||
heroInfos.set(hid, initHero);
|
||||
figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid });
|
||||
incHeroNum ++;
|
||||
}
|
||||
await unlockFigure(sid, roleId, figureConditions);
|
||||
|
||||
let roleUpdata: RoleUpdate = { heroNumUpdatedAt: nowSeconds() };
|
||||
if(initRoleInfos) {
|
||||
roleUpdata = { ...initRoleInfos, ...roleUpdata }
|
||||
}
|
||||
let { heroes } = await calculateCes(HERO_SYSTEM_TYPE.INIT, roleId, serverId, sid, heroInfos, roleUpdata, { heroNum: incHeroNum }, { isInitRole: !!initRoleInfos });
|
||||
for(let hero of heroes) {
|
||||
showHeroes.push(new HeroShowParam(hero));
|
||||
resultHeroes.push(hero);
|
||||
pushGetHero(roleId, roleName, serverId, hero);
|
||||
}
|
||||
|
||||
await SkinModel.insertSkins(roleId, roleName, skins);
|
||||
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, getSkinPushMsg(resultHeroes, skins), sid);
|
||||
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_UPDATE, { heroes: heroes.map(hero => new HeroParam(hero)) }, sid);
|
||||
}
|
||||
|
||||
if (pieces.length > 0) {
|
||||
let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE);
|
||||
resultItems = goods;
|
||||
}
|
||||
await checkTaskInCreateHero(serverId, roleId, sid, resultHeroes.length, resultHeroes);
|
||||
return { heroes: showHeroes, resultHeroes, goods: resultItems }
|
||||
}
|
||||
|
||||
export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) {
|
||||
let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getSkinPushMsg(resultHeroes: HeroType[], skins: SkinUpdate[]) {
|
||||
let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息
|
||||
for(let { hid, skins } of resultHeroes) {
|
||||
skinPushMessages.heros.push({ hid, skins });
|
||||
}
|
||||
for(let { id, hid } of skins) {
|
||||
skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN })
|
||||
}
|
||||
return skinPushMessages;
|
||||
}
|
||||
import { FIGURE_UNLOCK_CONDITION, ITEM_CHANGE_REASON, REDIS_KEY, STATUS, TASK_TYPE, HERO_SYSTEM_TYPE, LINEUP_NUM, COUNTER, PUSH_ROUTE } from "@consts";
|
||||
import { SkinModel } from "@db/Skin";
|
||||
import { HeroModel, HeroSkin, HeroType, HeroUpdate } from "@db/Hero";
|
||||
import { SkinUpdate } from "@db/Skin";
|
||||
import { nowSeconds } from "@pubUtils/timeUtil";
|
||||
import { CreateHeroParam, HeroParam, HeroShowParam } from "@domain/roleField/hero";
|
||||
import { ItemInter, RewardInter } from "@pubUtils/interface";
|
||||
import { transPiece } from "./util";
|
||||
import { addItems, unlockFigure, } from "./rewardService";
|
||||
import { CounterModel } from "@db/Counter";
|
||||
import { calculateCes } from "../playerCeService";
|
||||
import { RoleUpdate } from "@db/Role";
|
||||
import { sendMessageToUserWithSuc } from "../pushService";
|
||||
import { checkTaskInCreateHero } from "../task/taskService";
|
||||
import { filterHeroes } from "../dataService";
|
||||
import { pushGetHero } from "../sysChatService";
|
||||
|
||||
/**
|
||||
* 创建多个武将
|
||||
* @param roleId
|
||||
* @param sid
|
||||
* @param serverId
|
||||
* @param heroInfo
|
||||
*/
|
||||
export async function createHeroes(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam[], initRoleInfos?: RoleUpdate) {
|
||||
heroInfo = filterHeroes(heroInfo, obj => obj.hid, roleId);
|
||||
let hids = heroInfo.map(cur => cur.hid);
|
||||
let userHeroesMap = await HeroModel.findMapByHidRange(hids, roleId);
|
||||
|
||||
let createHeroeInfos: CreateHeroParam[] = [], pieces: ItemInter[] = [];
|
||||
for (let h of heroInfo) {
|
||||
let heroCount = h.count || 1;
|
||||
if (userHeroesMap.has(h.hid)) {
|
||||
let { pieceId, count } = transPiece(h.hid);
|
||||
pieces.push({ id: pieceId, count: count * heroCount });
|
||||
} else {
|
||||
createHeroeInfos.push(h);
|
||||
userHeroesMap.set(h.hid, null);
|
||||
if (heroCount > 1) {
|
||||
let { pieceId, count } = transPiece(h.hid);
|
||||
pieces.push({ id: pieceId, count: count * (heroCount - 1) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let resultHeroes: HeroType[] = [], resultItems: RewardInter[] = [], showHeroes: HeroShowParam[] = [];
|
||||
let figureConditions: { type: FIGURE_UNLOCK_CONDITION, paramHid: number }[] = [];
|
||||
let incHeroNum = 0;
|
||||
let skins: SkinUpdate[] = [];
|
||||
if (createHeroeInfos.length > 0) {
|
||||
let heroInfos = new Map<number, HeroUpdate>();
|
||||
for(let {hid, ...info} of createHeroeInfos) {
|
||||
let originSkins = await SkinModel.findbyRoleAndHid(roleId, hid);
|
||||
let initSkin = SkinModel.getInitInfo(hid);
|
||||
skins.push(initSkin); // 初始皮肤
|
||||
let seqId = await CounterModel.getNewCounter(COUNTER.HID) || -1;
|
||||
let initHeroSkins = [initSkin, ...originSkins].map((skin, index) => new HeroSkin(skin, index == 0));
|
||||
let initHero = HeroModel.getInitInfo(hid, { ...info, seqId, serverId, roleId, roleName, skins: initHeroSkins });
|
||||
heroInfos.set(hid, initHero);
|
||||
figureConditions.push({ type: FIGURE_UNLOCK_CONDITION.GET_HERO, paramHid: hid });
|
||||
incHeroNum ++;
|
||||
}
|
||||
await unlockFigure(sid, roleId, figureConditions);
|
||||
|
||||
let roleUpdata: RoleUpdate = { heroNumUpdatedAt: nowSeconds() };
|
||||
if(initRoleInfos) {
|
||||
roleUpdata = { ...initRoleInfos, ...roleUpdata }
|
||||
}
|
||||
let { heroes } = await calculateCes(HERO_SYSTEM_TYPE.INIT, roleId, serverId, sid, heroInfos, roleUpdata, { heroNum: incHeroNum }, { isInitRole: !!initRoleInfos });
|
||||
for(let hero of heroes) {
|
||||
showHeroes.push(new HeroShowParam(hero));
|
||||
resultHeroes.push(hero);
|
||||
pushGetHero(roleId, roleName, serverId, hero);
|
||||
}
|
||||
|
||||
await SkinModel.insertSkins(roleId, roleName, skins);
|
||||
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_SKIN_CHANGE, getSkinPushMsg(resultHeroes, skins), sid);
|
||||
sendMessageToUserWithSuc(roleId, PUSH_ROUTE.HERO_UPDATE, { heroes: heroes.map(hero => new HeroParam(hero)) }, sid);
|
||||
}
|
||||
|
||||
if (pieces.length > 0) {
|
||||
let goods = await addItems(roleId, roleName, sid, pieces, ITEM_CHANGE_REASON.HERO_TRANSFER_PIECE);
|
||||
resultItems = goods;
|
||||
}
|
||||
await checkTaskInCreateHero(serverId, roleId, sid, resultHeroes.length, resultHeroes);
|
||||
return { heroes: showHeroes, resultHeroes, goods: resultItems }
|
||||
}
|
||||
|
||||
export async function createHero(roleId: string, roleName: string, sid: string, serverId: number, heroInfo: CreateHeroParam) {
|
||||
let result = await createHeroes(roleId, roleName, sid, serverId, [heroInfo]);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getSkinPushMsg(resultHeroes: HeroType[], skins: SkinUpdate[]) {
|
||||
let skinPushMessages: {heros: {skins: HeroSkin[], hid: number}[], skins: {id: number, hid: number, inc: number, reason: number }[]} = { heros: [], skins:[] }; // 皮肤推送信息
|
||||
for(let { hid, skins } of resultHeroes) {
|
||||
skinPushMessages.heros.push({ hid, skins });
|
||||
}
|
||||
for(let { id, hid } of skins) {
|
||||
skinPushMessages.skins.push({ id, hid, inc: 1, reason: ITEM_CHANGE_REASON.GET_HERO_UNLOCK_SKIN })
|
||||
}
|
||||
return skinPushMessages;
|
||||
}
|
||||
|
||||
@@ -1,488 +1,488 @@
|
||||
import { EQUIP_EPLACEID, EQUIP_STONE, FRIENDSHIP_INDEX, HERO_SYSTEM_TYPE, LINEUP_NUM, RESONANCE, RESONANCE_SORT_TYPE } from "../../consts";
|
||||
import { ArtifactModel } from "../../db/Artifact";
|
||||
import { EPlace, HeroModel, HeroType } from "../../db/Hero";
|
||||
import { JewelModel, JewelType } from "../../db/Jewel";
|
||||
import { ResonanceModel, ResonanceType } from "../../db/Resonance";
|
||||
import { RoleModel } from "../../db/Role";
|
||||
import { HeroParam } from "../../domain/roleField/hero";
|
||||
import { gameData, getEquipByJobClassAndEPlace } from "../../pubUtils/data";
|
||||
import { ReturnResonanceParam } from "../../pubUtils/interface";
|
||||
import { calculateCeWithHeroes } from "../playerCeService";
|
||||
import { getNewJob, initSkinTalent } from "../roleService";
|
||||
import { pick } from 'underscore';
|
||||
import * as util from 'util';
|
||||
|
||||
export async function refreshResonanceData(roleId: string, serverId: number, sid: string) {
|
||||
let resonanceDatas: ReturnResonanceParam[] = [];
|
||||
let resonanceLv = {}, resonanceJob = {}, resonanceCon = [], resonanceEquip = [], resonanceEpQuality = [], resonanceEpStar = [], resonanceJewel = [], resonanceStone = [];
|
||||
|
||||
let role = await RoleModel.findByRoleId(roleId);
|
||||
let topHids = role.topLineup.map(cur => cur.hid);
|
||||
if (topHids.length < LINEUP_NUM) return { resonanceDatas };
|
||||
|
||||
let { dbResonanceMap, newPositionArr, posHids } = await getResonanceDataMap(roleId);
|
||||
resonanceDatas = newPositionArr;
|
||||
|
||||
let dbHeroes: HeroType[] = await HeroModel.findByHidsAndRole(roleId, [...topHids, ...posHids]);
|
||||
|
||||
let topLineHeroes: HeroType[] = [];
|
||||
for (const top of role.topLineup) {
|
||||
topLineHeroes.push(dbHeroes.find(cur => cur.hid == top.hid));
|
||||
}
|
||||
|
||||
let dbJewelMap = await getJewelDataMap(dbHeroes);
|
||||
|
||||
// 武将等级
|
||||
let topLineHero: HeroType = sortData(topLineHeroes, RESONANCE_SORT_TYPE.LV);
|
||||
resonanceLv = { hid: topLineHero.hid, lv: topLineHero.lv };
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
hero.lv = topLineHero.lv;
|
||||
hero.exp = topLineHero.exp;
|
||||
}
|
||||
|
||||
// 职业(职阶、天赋)
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JOBSTAGE);
|
||||
resonanceJob = { hid: topLineHero.hid, job: topLineHero.job, jobStage: topLineHero.jobStage };
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let preJobStage = hero.jobStage;
|
||||
hero.jobStage = topLineHero.jobStage;
|
||||
hero.job = getNewJob(hero, topLineHero.job);
|
||||
|
||||
if (preJobStage != hero.jobStage) {
|
||||
//天赋树置空
|
||||
hero.skins = initSkinTalent(hero.skins || []);
|
||||
}
|
||||
}
|
||||
|
||||
// 羁绊1, 2, 3
|
||||
for (let index = 1; index <= FRIENDSHIP_INDEX.THREE; index++) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.CONNECT, index);
|
||||
const topDicShipId = gameData.friendShipByIndex.get(`${topLineHero.hid}_${index}`);
|
||||
const topShipData = (topLineHero.connections || []).find(cur => cur.shipId == topDicShipId);
|
||||
resonanceCon.push({ hid: topLineHero.hid, index, level: topShipData?.level || 0 });
|
||||
if (!topShipData) continue;
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
const dicShipId = gameData.friendShipByIndex.get(`${hero.hid}_${index}`)
|
||||
let shipData = hero.connections.find(cur => cur.shipId == dicShipId);
|
||||
const dicShipData = gameData.friendShipsByLv.get(`${hid}_${dicShipId}_${topShipData?.level || 0}`);
|
||||
let sign = true;
|
||||
for (let hi of dicShipData?.hids || []) {
|
||||
if (!dbHeroes.find(cur => cur.hid == hi)) {
|
||||
sign = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sign) continue;
|
||||
if (!shipData) hero.connections.push({ shipId: dicShipId, level: topShipData?.level || 0, exp: topShipData?.exp || 0 });
|
||||
else {
|
||||
shipData.shipId = dicShipId
|
||||
shipData.exp = topShipData?.exp || 0;
|
||||
shipData.level = topShipData?.level || 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 装备 1武器,2衣甲,3帽子,4鞋子
|
||||
for (let id = 1; id <= EQUIP_EPLACEID.SHOE_ID; id++) {
|
||||
//装备强化
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_LV, id);
|
||||
let topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEquip.push({ hid: topLineHero.hid, id, lv: 0 });
|
||||
else
|
||||
resonanceEquip.push({ hid: topLineHero.hid, id, lv: topLineHeroEplace?.lv || 0 });
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.lv) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
}
|
||||
ePlaceData.lv = topLineHeroEplace.lv;
|
||||
}
|
||||
|
||||
//装备升品
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_QUALITY, id);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: 0, qualityStage: 0 })
|
||||
else
|
||||
resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: topLineHeroEplace?.quality || 0, qualityStage: topLineHeroEplace?.qualityStage || 0 })
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || (!topLineHeroEplace.quality && !topLineHeroEplace.qualityStage)) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.quality = topLineHeroEplace.quality;
|
||||
ePlaceData.qualityStage = topLineHeroEplace.qualityStage;
|
||||
}
|
||||
|
||||
//装备精练
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_STAR, id);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEpStar.push({ hid: topLineHero.hid, id, star: 0, starStage: 0 })
|
||||
else
|
||||
resonanceEpStar.push({ hid: topLineHero.hid, id, star: topLineHeroEplace?.star || 0, starStage: topLineHeroEplace?.starStage || 0 })
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || (!topLineHeroEplace.star && !topLineHeroEplace.starStage)) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.star = topLineHeroEplace.star;
|
||||
ePlaceData.starStage = topLineHeroEplace.starStage;
|
||||
}
|
||||
|
||||
//天晶
|
||||
if (RESONANCE.JEWEL) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JEWEL, id, dbJewelMap);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceJewel.push({ hid: topLineHero.hid, id, jewel: 0 });
|
||||
else
|
||||
resonanceJewel.push({ hid: topLineHero.hid, id, jewel: topLineHeroEplace?.jewel || 0 });
|
||||
|
||||
//破,御,护,命
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.jewel) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.jewel = topLineHeroEplace.jewel;
|
||||
}
|
||||
}
|
||||
|
||||
//地玉
|
||||
if (RESONANCE.STONE) {
|
||||
//破,御,护,命 1,2,3
|
||||
resonanceStone.push({ id, stones: [] });
|
||||
for (let index = 1; index <= EQUIP_STONE.THREE; index++) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.STONE, id, null, index);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
resonanceStone.find(cur => cur.id == id).stones.push({ hid: topLineHero.hid, id: index, stone: 0 });
|
||||
if (topLineHeroEplace && topLineHeroEplace.stones) {
|
||||
const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index);
|
||||
if (topLineHeroStone)
|
||||
resonanceStone.find(cur => cur.id == id).stones.find(cur => cur.id == index).stone = topLineHeroStone.stone;
|
||||
}
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.stones) continue;
|
||||
const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index);
|
||||
if (!topLineHeroStone || !topLineHeroStone.stone) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.stones.find(cur => cur.id == index).stone = topLineHeroStone.stone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let newHeroes: HeroType[] = [];
|
||||
for (let hero of dbHeroes) {
|
||||
if (dbResonanceMap.has(hero.hid)) newHeroes.push(hero);
|
||||
}
|
||||
|
||||
// 重新计算战力
|
||||
if (newHeroes.length > 0) {
|
||||
let artifacts = await ArtifactModel.findbyHids(roleId, posHids);
|
||||
let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, newHeroes, { jewels: [...dbJewelMap.values()], heroes: newHeroes, artifacts });
|
||||
for (let hero of (heroes || [])) {
|
||||
const { hid } = hero;
|
||||
const heroResult = new HeroParam(hero);
|
||||
resonanceDatas.push({ isResonance: true, position: dbResonanceMap.get(hid).position, ...pick(heroResult, ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) });
|
||||
}
|
||||
}
|
||||
|
||||
return { resonanceDatas, resonanceLv, resonanceJob, resonanceCon, resonanceEquip, resonanceEpQuality, resonanceEpStar, resonanceJewel, resonanceStone };
|
||||
}
|
||||
|
||||
|
||||
export function sortData(heroes: HeroType[], sortType: number, findType?: number, jewelMap?: Map<number, JewelType>, extendValue?: number) {
|
||||
switch (sortType) {
|
||||
case RESONANCE_SORT_TYPE.LV:
|
||||
{
|
||||
heroes.sort((a, b) => {
|
||||
if (a.lv !== b.lv) {
|
||||
return b.lv - a.lv;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.JOBSTAGE:
|
||||
{
|
||||
heroes.sort((a, b) => {
|
||||
let gradeA = gameData.job.get(a.job)?.grade || 0;
|
||||
let gradeB = gameData.job.get(b.job)?.grade || 0;
|
||||
|
||||
if (gradeA != gradeB) {
|
||||
return gradeB - gradeA;
|
||||
}
|
||||
else if (a.jobStage !== b.jobStage) {
|
||||
return b.jobStage - a.jobStage;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.CONNECT:
|
||||
{
|
||||
heroes = sortByConnect(heroes, findType)
|
||||
break;
|
||||
}
|
||||
|
||||
case RESONANCE_SORT_TYPE.EQUIP_LV:
|
||||
{
|
||||
heroes = sortByEquipLv(heroes, findType);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.EQUIP_QUALITY:
|
||||
{
|
||||
heroes = sortByEquipQuality(heroes, findType);
|
||||
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.EQUIP_STAR:
|
||||
{
|
||||
heroes = sortByEquipStar(heroes, findType);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.JEWEL:
|
||||
{
|
||||
heroes = sortByEquipJewel(heroes, findType, jewelMap);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.STONE:
|
||||
{
|
||||
heroes = sortByEquipStone(heroes, findType, extendValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let topLineHeroes: HeroType[] = heroes;
|
||||
|
||||
// console.log('-x-x--x-x-x-x-x-x-x-x-x- topLineHeroes', util.inspect(heroes, { depth: null }));
|
||||
return topLineHeroes[LINEUP_NUM - 1];
|
||||
}
|
||||
|
||||
export function sortByConnect(heroes: HeroType[], index: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const dicShipIdA = gameData.friendShipByIndex.get(`${a.hid}_${index}`)
|
||||
const valA = a.connections.find(obj => obj.shipId === dicShipIdA)?.level || 0;
|
||||
const dicShipIdB = gameData.friendShipByIndex.get(`${b.hid}_${index}`)
|
||||
const valB = b.connections.find(obj => obj.shipId === dicShipIdB)?.level || 0;
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
|
||||
return heroes
|
||||
}
|
||||
|
||||
export function sortByEquipLv(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.lv || 0
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.lv || 0;
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipQuality(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.quality || 0;
|
||||
const valStageA = a.ePlace.find(obj => obj.id == id)?.qualityStage || 0;
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.quality || 0;
|
||||
const valStageB = b.ePlace.find(obj => obj.id == id)?.qualityStage || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
}
|
||||
else if (valStageA != valStageB) {
|
||||
return valStageB - valStageA;
|
||||
}
|
||||
else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipStar(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.star || 0;
|
||||
const valStageA = a.ePlace.find(obj => obj.id == id)?.starStage || 0;
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.star || 0;
|
||||
const valStageB = b.ePlace.find(obj => obj.id == id)?.starStage || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
}
|
||||
else if (valStageA != valStageB) {
|
||||
return valStageB - valStageA;
|
||||
}
|
||||
else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipJewel(heroes: HeroType[], eplaceId: number, jewelMap: Map<number, JewelType>) {
|
||||
heroes.sort((a, b) => {
|
||||
const jewelA = a.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0
|
||||
let jewelAData = jewelMap.get(jewelA);
|
||||
const dicJewelALv = gameData.jewel.get(jewelAData?.id || 0)?.lv || 0;
|
||||
let valA = 0;
|
||||
if (jewelAData) {
|
||||
if (jewelAData.randSe && jewelAData.randSe.length > 0) {
|
||||
for (let { seid, rand } of jewelAData.randSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue;
|
||||
valA += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
if (jewelAData.rareSe && jewelAData.rareSe.length > 0) {
|
||||
for (let { seid, rand } of jewelAData.rareSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue;
|
||||
valA += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const jewelB = b.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0
|
||||
let jewelBData = jewelMap.get(jewelB);
|
||||
const dicJewelBLv = gameData.jewel.get(jewelBData?.id || 0)?.lv || 0;
|
||||
let valB = 0;
|
||||
if (jewelBData) {
|
||||
if (jewelBData.randSe && jewelBData.randSe.length > 0) {
|
||||
for (let { seid, rand } of jewelBData.randSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue;
|
||||
valB += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
if (jewelBData.rareSe && jewelBData.rareSe.length > 0) {
|
||||
for (let { seid, rand } of jewelBData.rareSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue;
|
||||
valB += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dicJewelALv != dicJewelBLv) {
|
||||
return dicJewelBLv - dicJewelALv;
|
||||
}
|
||||
else if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipStone(heroes: HeroType[], id: number, extendValue: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const stoneA = a.ePlace.find(obj => obj.id == id)?.stones || [];
|
||||
const stoneIdA = stoneA.find(obj => obj.id == extendValue)?.stone || 0;
|
||||
const valA = gameData.stone.get(stoneIdA)?.lv || 0;
|
||||
const stoneB = b.ePlace.find(obj => obj.id == id)?.stones || [];
|
||||
const stoneIdB = stoneB.find(obj => obj.id == extendValue)?.stone || 0;
|
||||
const valB = gameData.stone.get(stoneIdB)?.lv || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
|
||||
export async function getResonanceDataMap(roleId: string) {
|
||||
let dbResonance = await ResonanceModel.findByRoleId(roleId);
|
||||
let dbResonanceMap = new Map<number, ResonanceType>();
|
||||
let newPositionArr: ReturnResonanceParam[] = [], posHids: number[] = [];
|
||||
for (let obj of dbResonance) {
|
||||
if (obj.hid) {
|
||||
dbResonanceMap.set(obj.hid, obj);
|
||||
posHids.push(obj.hid);
|
||||
}
|
||||
else newPositionArr.push({ position: obj.position });
|
||||
|
||||
}
|
||||
return { dbResonanceMap, newPositionArr, posHids };
|
||||
}
|
||||
|
||||
export async function getJewelDataMap(heroes: HeroType[]) {
|
||||
let dbJewelMap = new Map<number, JewelType>();
|
||||
let seqIds = [];
|
||||
for (let hero of heroes) {
|
||||
const { ePlace } = hero;
|
||||
if (!ePlace || ePlace.length == 0) continue;
|
||||
for (let { jewel } of ePlace) {
|
||||
if (jewel == 0) continue;
|
||||
seqIds.push(jewel);
|
||||
}
|
||||
}
|
||||
if (seqIds.length > 0) {
|
||||
let dbJewels = await JewelModel.findbySeqIds(seqIds);
|
||||
if (dbJewels.length > 0) {
|
||||
for (let obj of dbJewels) {
|
||||
dbJewelMap.set(obj.seqId, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dbJewelMap;
|
||||
}
|
||||
|
||||
export function getInitEplace(id: number, skinId: number) {
|
||||
const dicHero = gameData.hero.get(skinId)
|
||||
const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id);
|
||||
return new EPlace(id, dicEquip.id);
|
||||
}
|
||||
import { EQUIP_EPLACEID, EQUIP_STONE, FRIENDSHIP_INDEX, HERO_SYSTEM_TYPE, LINEUP_NUM, RESONANCE, RESONANCE_SORT_TYPE } from "@consts";
|
||||
import { ArtifactModel } from "@db/Artifact";
|
||||
import { EPlace, HeroModel, HeroType } from "@db/Hero";
|
||||
import { JewelModel, JewelType } from "@db/Jewel";
|
||||
import { ResonanceModel, ResonanceType } from "@db/Resonance";
|
||||
import { RoleModel } from "@db/Role";
|
||||
import { HeroParam } from "@domain/roleField/hero";
|
||||
import { gameData, getEquipByJobClassAndEPlace } from "@pubUtils/data";
|
||||
import { ReturnResonanceParam } from "@pubUtils/interface";
|
||||
import { calculateCeWithHeroes } from "../playerCeService";
|
||||
import { getNewJob, initSkinTalent } from "../roleService";
|
||||
import { pick } from 'underscore';
|
||||
import * as util from 'util';
|
||||
|
||||
export async function refreshResonanceData(roleId: string, serverId: number, sid: string) {
|
||||
let resonanceDatas: ReturnResonanceParam[] = [];
|
||||
let resonanceLv = {}, resonanceJob = {}, resonanceCon = [], resonanceEquip = [], resonanceEpQuality = [], resonanceEpStar = [], resonanceJewel = [], resonanceStone = [];
|
||||
|
||||
let role = await RoleModel.findByRoleId(roleId);
|
||||
let topHids = role.topLineup.map(cur => cur.hid);
|
||||
if (topHids.length < LINEUP_NUM) return { resonanceDatas };
|
||||
|
||||
let { dbResonanceMap, newPositionArr, posHids } = await getResonanceDataMap(roleId);
|
||||
resonanceDatas = newPositionArr;
|
||||
|
||||
let dbHeroes: HeroType[] = await HeroModel.findByHidsAndRole(roleId, [...topHids, ...posHids]);
|
||||
|
||||
let topLineHeroes: HeroType[] = [];
|
||||
for (const top of role.topLineup) {
|
||||
topLineHeroes.push(dbHeroes.find(cur => cur.hid == top.hid));
|
||||
}
|
||||
|
||||
let dbJewelMap = await getJewelDataMap(dbHeroes);
|
||||
|
||||
// 武将等级
|
||||
let topLineHero: HeroType = sortData(topLineHeroes, RESONANCE_SORT_TYPE.LV);
|
||||
resonanceLv = { hid: topLineHero.hid, lv: topLineHero.lv };
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
hero.lv = topLineHero.lv;
|
||||
hero.exp = topLineHero.exp;
|
||||
}
|
||||
|
||||
// 职业(职阶、天赋)
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JOBSTAGE);
|
||||
resonanceJob = { hid: topLineHero.hid, job: topLineHero.job, jobStage: topLineHero.jobStage };
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let preJobStage = hero.jobStage;
|
||||
hero.jobStage = topLineHero.jobStage;
|
||||
hero.job = getNewJob(hero, topLineHero.job);
|
||||
|
||||
if (preJobStage != hero.jobStage) {
|
||||
//天赋树置空
|
||||
hero.skins = initSkinTalent(hero.skins || []);
|
||||
}
|
||||
}
|
||||
|
||||
// 羁绊1, 2, 3
|
||||
for (let index = 1; index <= FRIENDSHIP_INDEX.THREE; index++) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.CONNECT, index);
|
||||
const topDicShipId = gameData.friendShipByIndex.get(`${topLineHero.hid}_${index}`);
|
||||
const topShipData = (topLineHero.connections || []).find(cur => cur.shipId == topDicShipId);
|
||||
resonanceCon.push({ hid: topLineHero.hid, index, level: topShipData?.level || 0 });
|
||||
if (!topShipData) continue;
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
const dicShipId = gameData.friendShipByIndex.get(`${hero.hid}_${index}`)
|
||||
let shipData = hero.connections.find(cur => cur.shipId == dicShipId);
|
||||
const dicShipData = gameData.friendShipsByLv.get(`${hid}_${dicShipId}_${topShipData?.level || 0}`);
|
||||
let sign = true;
|
||||
for (let hi of dicShipData?.hids || []) {
|
||||
if (!dbHeroes.find(cur => cur.hid == hi)) {
|
||||
sign = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sign) continue;
|
||||
if (!shipData) hero.connections.push({ shipId: dicShipId, level: topShipData?.level || 0, exp: topShipData?.exp || 0 });
|
||||
else {
|
||||
shipData.shipId = dicShipId
|
||||
shipData.exp = topShipData?.exp || 0;
|
||||
shipData.level = topShipData?.level || 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 装备 1武器,2衣甲,3帽子,4鞋子
|
||||
for (let id = 1; id <= EQUIP_EPLACEID.SHOE_ID; id++) {
|
||||
//装备强化
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_LV, id);
|
||||
let topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEquip.push({ hid: topLineHero.hid, id, lv: 0 });
|
||||
else
|
||||
resonanceEquip.push({ hid: topLineHero.hid, id, lv: topLineHeroEplace?.lv || 0 });
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.lv) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
}
|
||||
ePlaceData.lv = topLineHeroEplace.lv;
|
||||
}
|
||||
|
||||
//装备升品
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_QUALITY, id);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: 0, qualityStage: 0 })
|
||||
else
|
||||
resonanceEpQuality.push({ hid: topLineHero.hid, id, quality: topLineHeroEplace?.quality || 0, qualityStage: topLineHeroEplace?.qualityStage || 0 })
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || (!topLineHeroEplace.quality && !topLineHeroEplace.qualityStage)) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.quality = topLineHeroEplace.quality;
|
||||
ePlaceData.qualityStage = topLineHeroEplace.qualityStage;
|
||||
}
|
||||
|
||||
//装备精练
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.EQUIP_STAR, id);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceEpStar.push({ hid: topLineHero.hid, id, star: 0, starStage: 0 })
|
||||
else
|
||||
resonanceEpStar.push({ hid: topLineHero.hid, id, star: topLineHeroEplace?.star || 0, starStage: topLineHeroEplace?.starStage || 0 })
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || (!topLineHeroEplace.star && !topLineHeroEplace.starStage)) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.star = topLineHeroEplace.star;
|
||||
ePlaceData.starStage = topLineHeroEplace.starStage;
|
||||
}
|
||||
|
||||
//天晶
|
||||
if (RESONANCE.JEWEL) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.JEWEL, id, dbJewelMap);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
if (!topLineHeroEplace)
|
||||
resonanceJewel.push({ hid: topLineHero.hid, id, jewel: 0 });
|
||||
else
|
||||
resonanceJewel.push({ hid: topLineHero.hid, id, jewel: topLineHeroEplace?.jewel || 0 });
|
||||
|
||||
//破,御,护,命
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.jewel) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.jewel = topLineHeroEplace.jewel;
|
||||
}
|
||||
}
|
||||
|
||||
//地玉
|
||||
if (RESONANCE.STONE) {
|
||||
//破,御,护,命 1,2,3
|
||||
resonanceStone.push({ id, stones: [] });
|
||||
for (let index = 1; index <= EQUIP_STONE.THREE; index++) {
|
||||
topLineHero = sortData(topLineHeroes, RESONANCE_SORT_TYPE.STONE, id, null, index);
|
||||
topLineHeroEplace = topLineHero.ePlace.find(cur => cur.id == id);
|
||||
resonanceStone.find(cur => cur.id == id).stones.push({ hid: topLineHero.hid, id: index, stone: 0 });
|
||||
if (topLineHeroEplace && topLineHeroEplace.stones) {
|
||||
const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index);
|
||||
if (topLineHeroStone)
|
||||
resonanceStone.find(cur => cur.id == id).stones.find(cur => cur.id == index).stone = topLineHeroStone.stone;
|
||||
}
|
||||
|
||||
for (let [hid] of dbResonanceMap) {
|
||||
if (!topLineHeroEplace || !topLineHeroEplace.stones) continue;
|
||||
const topLineHeroStone = topLineHeroEplace.stones.find(cur => cur.id == index);
|
||||
if (!topLineHeroStone || !topLineHeroStone.stone) continue;
|
||||
let hero = dbHeroes.find(cur => cur.hid == hid);
|
||||
let ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
if (!ePlaceData) {
|
||||
hero.ePlace.push({ ...getInitEplace(id, hero.skinId) });
|
||||
ePlaceData = hero.ePlace.find(cur => cur.id == id);
|
||||
};
|
||||
ePlaceData.stones.find(cur => cur.id == index).stone = topLineHeroStone.stone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let newHeroes: HeroType[] = [];
|
||||
for (let hero of dbHeroes) {
|
||||
if (dbResonanceMap.has(hero.hid)) newHeroes.push(hero);
|
||||
}
|
||||
|
||||
// 重新计算战力
|
||||
if (newHeroes.length > 0) {
|
||||
let artifacts = await ArtifactModel.findbyHids(roleId, posHids);
|
||||
let { heroes } = await calculateCeWithHeroes(HERO_SYSTEM_TYPE.RESONANCE_CAL, roleId, serverId, sid, newHeroes, { jewels: [...dbJewelMap.values()], heroes: newHeroes, artifacts });
|
||||
for (let hero of (heroes || [])) {
|
||||
const { hid } = hero;
|
||||
const heroResult = new HeroParam(hero);
|
||||
resonanceDatas.push({ isResonance: true, position: dbResonanceMap.get(hid).position, ...pick(heroResult, ['hid', 'seqId', 'lv', 'exp', 'job', 'jobStage', 'talent', 'usedTalentPoint', 'totalTalentPoint', 'connections', 'ePlace', 'ce']) });
|
||||
}
|
||||
}
|
||||
|
||||
return { resonanceDatas, resonanceLv, resonanceJob, resonanceCon, resonanceEquip, resonanceEpQuality, resonanceEpStar, resonanceJewel, resonanceStone };
|
||||
}
|
||||
|
||||
|
||||
export function sortData(heroes: HeroType[], sortType: number, findType?: number, jewelMap?: Map<number, JewelType>, extendValue?: number) {
|
||||
switch (sortType) {
|
||||
case RESONANCE_SORT_TYPE.LV:
|
||||
{
|
||||
heroes.sort((a, b) => {
|
||||
if (a.lv !== b.lv) {
|
||||
return b.lv - a.lv;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.JOBSTAGE:
|
||||
{
|
||||
heroes.sort((a, b) => {
|
||||
let gradeA = gameData.job.get(a.job)?.grade || 0;
|
||||
let gradeB = gameData.job.get(b.job)?.grade || 0;
|
||||
|
||||
if (gradeA != gradeB) {
|
||||
return gradeB - gradeA;
|
||||
}
|
||||
else if (a.jobStage !== b.jobStage) {
|
||||
return b.jobStage - a.jobStage;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.CONNECT:
|
||||
{
|
||||
heroes = sortByConnect(heroes, findType)
|
||||
break;
|
||||
}
|
||||
|
||||
case RESONANCE_SORT_TYPE.EQUIP_LV:
|
||||
{
|
||||
heroes = sortByEquipLv(heroes, findType);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.EQUIP_QUALITY:
|
||||
{
|
||||
heroes = sortByEquipQuality(heroes, findType);
|
||||
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.EQUIP_STAR:
|
||||
{
|
||||
heroes = sortByEquipStar(heroes, findType);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.JEWEL:
|
||||
{
|
||||
heroes = sortByEquipJewel(heroes, findType, jewelMap);
|
||||
break;
|
||||
}
|
||||
case RESONANCE_SORT_TYPE.STONE:
|
||||
{
|
||||
heroes = sortByEquipStone(heroes, findType, extendValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let topLineHeroes: HeroType[] = heroes;
|
||||
|
||||
// console.log('-x-x--x-x-x-x-x-x-x-x-x- topLineHeroes', util.inspect(heroes, { depth: null }));
|
||||
return topLineHeroes[LINEUP_NUM - 1];
|
||||
}
|
||||
|
||||
export function sortByConnect(heroes: HeroType[], index: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const dicShipIdA = gameData.friendShipByIndex.get(`${a.hid}_${index}`)
|
||||
const valA = a.connections.find(obj => obj.shipId === dicShipIdA)?.level || 0;
|
||||
const dicShipIdB = gameData.friendShipByIndex.get(`${b.hid}_${index}`)
|
||||
const valB = b.connections.find(obj => obj.shipId === dicShipIdB)?.level || 0;
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
|
||||
return heroes
|
||||
}
|
||||
|
||||
export function sortByEquipLv(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.lv || 0
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.lv || 0;
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipQuality(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.quality || 0;
|
||||
const valStageA = a.ePlace.find(obj => obj.id == id)?.qualityStage || 0;
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.quality || 0;
|
||||
const valStageB = b.ePlace.find(obj => obj.id == id)?.qualityStage || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
}
|
||||
else if (valStageA != valStageB) {
|
||||
return valStageB - valStageA;
|
||||
}
|
||||
else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipStar(heroes: HeroType[], id: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const valA = a.ePlace.find(obj => obj.id == id)?.star || 0;
|
||||
const valStageA = a.ePlace.find(obj => obj.id == id)?.starStage || 0;
|
||||
const valB = b.ePlace.find(obj => obj.id == id)?.star || 0;
|
||||
const valStageB = b.ePlace.find(obj => obj.id == id)?.starStage || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
}
|
||||
else if (valStageA != valStageB) {
|
||||
return valStageB - valStageA;
|
||||
}
|
||||
else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipJewel(heroes: HeroType[], eplaceId: number, jewelMap: Map<number, JewelType>) {
|
||||
heroes.sort((a, b) => {
|
||||
const jewelA = a.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0
|
||||
let jewelAData = jewelMap.get(jewelA);
|
||||
const dicJewelALv = gameData.jewel.get(jewelAData?.id || 0)?.lv || 0;
|
||||
let valA = 0;
|
||||
if (jewelAData) {
|
||||
if (jewelAData.randSe && jewelAData.randSe.length > 0) {
|
||||
for (let { seid, rand } of jewelAData.randSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue;
|
||||
valA += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
if (jewelAData.rareSe && jewelAData.rareSe.length > 0) {
|
||||
for (let { seid, rand } of jewelAData.rareSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || ((dicRandomEffectPool?.Max || 0) == 0)) continue;
|
||||
valA += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const jewelB = b.ePlace.find(obj => obj.id == eplaceId)?.jewel || 0
|
||||
let jewelBData = jewelMap.get(jewelB);
|
||||
const dicJewelBLv = gameData.jewel.get(jewelBData?.id || 0)?.lv || 0;
|
||||
let valB = 0;
|
||||
if (jewelBData) {
|
||||
if (jewelBData.randSe && jewelBData.randSe.length > 0) {
|
||||
for (let { seid, rand } of jewelBData.randSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue;
|
||||
valB += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
if (jewelBData.rareSe && jewelBData.rareSe.length > 0) {
|
||||
for (let { seid, rand } of jewelBData.rareSe) {
|
||||
let dicRandomEffectPool = gameData.randomEffectPool.get(seid);
|
||||
if (!dicRandomEffectPool) continue;
|
||||
if (!dicRandomEffectPool.Max) dicRandomEffectPool = gameData.randomEffectPool.get(1);
|
||||
if (!dicRandomEffectPool || (dicRandomEffectPool?.Max || 0) == 0) continue;
|
||||
valB += rand / (dicRandomEffectPool.Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dicJewelALv != dicJewelBLv) {
|
||||
return dicJewelBLv - dicJewelALv;
|
||||
}
|
||||
else if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
|
||||
return heroes;
|
||||
}
|
||||
|
||||
export function sortByEquipStone(heroes: HeroType[], id: number, extendValue: number) {
|
||||
heroes.sort((a, b) => {
|
||||
const stoneA = a.ePlace.find(obj => obj.id == id)?.stones || [];
|
||||
const stoneIdA = stoneA.find(obj => obj.id == extendValue)?.stone || 0;
|
||||
const valA = gameData.stone.get(stoneIdA)?.lv || 0;
|
||||
const stoneB = b.ePlace.find(obj => obj.id == id)?.stones || [];
|
||||
const stoneIdB = stoneB.find(obj => obj.id == extendValue)?.stone || 0;
|
||||
const valB = gameData.stone.get(stoneIdB)?.lv || 0;
|
||||
|
||||
if (valA != valB) {
|
||||
return valB - valA;
|
||||
} else {
|
||||
return b.ce - a.ce;
|
||||
}
|
||||
});
|
||||
return heroes;
|
||||
}
|
||||
|
||||
|
||||
export async function getResonanceDataMap(roleId: string) {
|
||||
let dbResonance = await ResonanceModel.findByRoleId(roleId);
|
||||
let dbResonanceMap = new Map<number, ResonanceType>();
|
||||
let newPositionArr: ReturnResonanceParam[] = [], posHids: number[] = [];
|
||||
for (let obj of dbResonance) {
|
||||
if (obj.hid) {
|
||||
dbResonanceMap.set(obj.hid, obj);
|
||||
posHids.push(obj.hid);
|
||||
}
|
||||
else newPositionArr.push({ position: obj.position });
|
||||
|
||||
}
|
||||
return { dbResonanceMap, newPositionArr, posHids };
|
||||
}
|
||||
|
||||
export async function getJewelDataMap(heroes: HeroType[]) {
|
||||
let dbJewelMap = new Map<number, JewelType>();
|
||||
let seqIds = [];
|
||||
for (let hero of heroes) {
|
||||
const { ePlace } = hero;
|
||||
if (!ePlace || ePlace.length == 0) continue;
|
||||
for (let { jewel } of ePlace) {
|
||||
if (jewel == 0) continue;
|
||||
seqIds.push(jewel);
|
||||
}
|
||||
}
|
||||
if (seqIds.length > 0) {
|
||||
let dbJewels = await JewelModel.findbySeqIds(seqIds);
|
||||
if (dbJewels.length > 0) {
|
||||
for (let obj of dbJewels) {
|
||||
dbJewelMap.set(obj.seqId, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dbJewelMap;
|
||||
}
|
||||
|
||||
export function getInitEplace(id: number, skinId: number) {
|
||||
const dicHero = gameData.hero.get(skinId)
|
||||
const dicEquip = getEquipByJobClassAndEPlace(dicHero?.jobClass, id);
|
||||
return new EPlace(id, dicEquip.id);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,139 +1,139 @@
|
||||
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, HANDLE_REWARD_TYPE, ITEM_CHANGE_REASON, CURRENCY_BY_TYPE } from '../../consts';
|
||||
import { ItemInter, RewardInter, } from '../../pubUtils/interface';
|
||||
import { gameData } from '../../pubUtils/data';
|
||||
import { errlogger } from '../../util/logger';
|
||||
|
||||
export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
|
||||
let items: { id: number, count: number }[] = []; // 可叠加道具
|
||||
let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备
|
||||
let artifacts: { seqId?: number|string, id?: number }[] = []; // 不可叠加宝物
|
||||
let gold: { count: number, isPay: boolean }[] = []; // 金币
|
||||
let coin: number[] = [];
|
||||
let ap: number = 0;
|
||||
let skins: number[] = [];
|
||||
let figures: number[] = [];
|
||||
let activityItems: { id: number, count: number, expireTime?: number }[] = []; // 可叠加道具
|
||||
|
||||
for(let good of goods) {
|
||||
if(good.count == 0) continue;
|
||||
let dicGood = gameData.goods.get(good.id);
|
||||
if(!dicGood) {
|
||||
errlogger.error(`物品 ${good.id} 未配置`);
|
||||
continue;
|
||||
}
|
||||
let dicItid = ITID.get(dicGood.itid);
|
||||
if(!dicItid) {
|
||||
errlogger.error(`itid ${dicGood.itid} 未配置`);
|
||||
continue;
|
||||
}
|
||||
let { type, table, isCurrency } = dicItid;
|
||||
if(table == ITEM_TABLE.JEWEL) { // 装备
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
for(let i = 0; i < good.count; i++) {
|
||||
jewels.push({ id: good.id, hid: good.hid })
|
||||
}
|
||||
} else {
|
||||
if(!!good.seqId) {
|
||||
jewels.push({ seqId: <number>good.seqId });
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ITEM) { // 可叠加道具
|
||||
let index = items.findIndex(cur => cur.id == good.id);
|
||||
if(index >= 0) {
|
||||
items[index].count += good.count;
|
||||
} else {
|
||||
items.push({ id: good.id, count: good.count });
|
||||
}
|
||||
} else if (table == ITEM_TABLE.SKIN) { // 皮肤,不可重复获得,不可删
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
let index = skins.indexOf(good.id);
|
||||
if (index == -1) {
|
||||
skins.push(good.id);
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ROLE) {
|
||||
if(isCurrency) { // 3种货币
|
||||
let dicCurrency = CURRENCY.get(good.id);
|
||||
if(dicCurrency) {
|
||||
if(dicCurrency.type == CURRENCY_TYPE.GOLD) { // 金币,区分付费和免费,默认免费
|
||||
let index = gold.findIndex(cur => cur.isPay == !!good.isPay);
|
||||
if(index >= 0) {
|
||||
gold[index].count += good.count;
|
||||
} else {
|
||||
gold.push({ count: good.count, isPay: !!good.isPay });
|
||||
}
|
||||
} else if (dicCurrency.type == CURRENCY_TYPE.COIN) { // 铜钱
|
||||
coin.push(good.count);
|
||||
} else if (dicCurrency.type == CURRENCY_TYPE.ACTION_POINT) { // 体力
|
||||
ap += good.count;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { // 头像等,不可重复获得,不可删
|
||||
let index = figures.indexOf(good.id);
|
||||
if (index == -1) {
|
||||
figures.push(good.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ARTIFACT) {
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
for(let i = 0; i < good.count; i++) {
|
||||
artifacts.push({ id: good.id })
|
||||
}
|
||||
} else {
|
||||
if(!!good.seqId) {
|
||||
artifacts.push({ seqId: good.seqId });
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ACTIVITY_ITEM) { // 活动道具,限时,可堆叠
|
||||
let index = activityItems.findIndex(cur => cur.id == good.id);
|
||||
if(index >= 0) {
|
||||
activityItems[index].count += good.count;
|
||||
} else {
|
||||
activityItems.push({ id: good.id, count: good.count, expireTime: good.expireTime });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems }
|
||||
}
|
||||
|
||||
export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
|
||||
let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason }
|
||||
}
|
||||
|
||||
export function getCoinEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
|
||||
let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN);
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason }
|
||||
}
|
||||
|
||||
export function combineItems(items: { id?: number, count?: number, seqId?: number|string, isBag?: boolean }[]) {
|
||||
let result: { id: number, count: number, seqId?: number|string, isBag?: boolean }[] = [];
|
||||
for(let { id, count = 1, seqId, isBag } of items) {
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
let dicItid = ITID.get(dicGoods.itid);
|
||||
if(dicItid.table != 'jewel' && dicItid.table != 'artifact') {
|
||||
let index = result.findIndex(cur => cur.id == id);
|
||||
if(index == -1) {
|
||||
result.push({ id, count, seqId, isBag });
|
||||
} else {
|
||||
result[index].count += count;
|
||||
}
|
||||
} else {
|
||||
result.push({ id, count, seqId, isBag });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export function transPiece(hid: number) {
|
||||
let dicHero = gameData.hero.get(hid);
|
||||
let count = gameData.heroTransPiece.get(dicHero.quality);
|
||||
return { pieceId: dicHero.pieceId, count }
|
||||
}
|
||||
import { ITID, CONSUME_TYPE, ITEM_TABLE, CURRENCY, CURRENCY_TYPE, HANDLE_REWARD_TYPE, ITEM_CHANGE_REASON, CURRENCY_BY_TYPE } from '@consts';
|
||||
import { ItemInter, RewardInter, } from '@pubUtils/interface';
|
||||
import { gameData } from '@pubUtils/data';
|
||||
import { errlogger } from '../../util/logger';
|
||||
|
||||
export function sortItems(goods: ItemInter[], handleType: HANDLE_REWARD_TYPE) {
|
||||
let items: { id: number, count: number }[] = []; // 可叠加道具
|
||||
let jewels: { seqId?: number, id?: number, hid?: number }[] = []; // 不可叠加装备
|
||||
let artifacts: { seqId?: number|string, id?: number }[] = []; // 不可叠加宝物
|
||||
let gold: { count: number, isPay: boolean }[] = []; // 金币
|
||||
let coin: number[] = [];
|
||||
let ap: number = 0;
|
||||
let skins: number[] = [];
|
||||
let figures: number[] = [];
|
||||
let activityItems: { id: number, count: number, expireTime?: number }[] = []; // 可叠加道具
|
||||
|
||||
for(let good of goods) {
|
||||
if(good.count == 0) continue;
|
||||
let dicGood = gameData.goods.get(good.id);
|
||||
if(!dicGood) {
|
||||
errlogger.error(`物品 ${good.id} 未配置`);
|
||||
continue;
|
||||
}
|
||||
let dicItid = ITID.get(dicGood.itid);
|
||||
if(!dicItid) {
|
||||
errlogger.error(`itid ${dicGood.itid} 未配置`);
|
||||
continue;
|
||||
}
|
||||
let { type, table, isCurrency } = dicItid;
|
||||
if(table == ITEM_TABLE.JEWEL) { // 装备
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
for(let i = 0; i < good.count; i++) {
|
||||
jewels.push({ id: good.id, hid: good.hid })
|
||||
}
|
||||
} else {
|
||||
if(!!good.seqId) {
|
||||
jewels.push({ seqId: <number>good.seqId });
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ITEM) { // 可叠加道具
|
||||
let index = items.findIndex(cur => cur.id == good.id);
|
||||
if(index >= 0) {
|
||||
items[index].count += good.count;
|
||||
} else {
|
||||
items.push({ id: good.id, count: good.count });
|
||||
}
|
||||
} else if (table == ITEM_TABLE.SKIN) { // 皮肤,不可重复获得,不可删
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
let index = skins.indexOf(good.id);
|
||||
if (index == -1) {
|
||||
skins.push(good.id);
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ROLE) {
|
||||
if(isCurrency) { // 3种货币
|
||||
let dicCurrency = CURRENCY.get(good.id);
|
||||
if(dicCurrency) {
|
||||
if(dicCurrency.type == CURRENCY_TYPE.GOLD) { // 金币,区分付费和免费,默认免费
|
||||
let index = gold.findIndex(cur => cur.isPay == !!good.isPay);
|
||||
if(index >= 0) {
|
||||
gold[index].count += good.count;
|
||||
} else {
|
||||
gold.push({ count: good.count, isPay: !!good.isPay });
|
||||
}
|
||||
} else if (dicCurrency.type == CURRENCY_TYPE.COIN) { // 铜钱
|
||||
coin.push(good.count);
|
||||
} else if (dicCurrency.type == CURRENCY_TYPE.ACTION_POINT) { // 体力
|
||||
ap += good.count;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (type == CONSUME_TYPE.HEAD || type == CONSUME_TYPE.FRAME || type == CONSUME_TYPE.SPINE) { // 头像等,不可重复获得,不可删
|
||||
let index = figures.indexOf(good.id);
|
||||
if (index == -1) {
|
||||
figures.push(good.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ARTIFACT) {
|
||||
if(handleType == HANDLE_REWARD_TYPE.RECEIVE) {
|
||||
for(let i = 0; i < good.count; i++) {
|
||||
artifacts.push({ id: good.id })
|
||||
}
|
||||
} else {
|
||||
if(!!good.seqId) {
|
||||
artifacts.push({ seqId: good.seqId });
|
||||
}
|
||||
}
|
||||
} else if (table == ITEM_TABLE.ACTIVITY_ITEM) { // 活动道具,限时,可堆叠
|
||||
let index = activityItems.findIndex(cur => cur.id == good.id);
|
||||
if(index >= 0) {
|
||||
activityItems[index].count += good.count;
|
||||
} else {
|
||||
activityItems.push({ id: good.id, count: good.count, expireTime: good.expireTime });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return { items, jewels, gold, coin, ap, skins, figures, artifacts, activityItems }
|
||||
}
|
||||
|
||||
export function getGoldEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
|
||||
let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason }
|
||||
}
|
||||
|
||||
export function getCoinEventProperties(inc: number, count: number, reason: ITEM_CHANGE_REASON) {
|
||||
let id = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN);
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
return { item_id: id, item_name: dicGoods.name, item_itid: dicGoods.itid, change_count: inc, change_after: count, change_reason: reason }
|
||||
}
|
||||
|
||||
export function combineItems(items: { id?: number, count?: number, seqId?: number|string, isBag?: boolean }[]) {
|
||||
let result: { id: number, count: number, seqId?: number|string, isBag?: boolean }[] = [];
|
||||
for(let { id, count = 1, seqId, isBag } of items) {
|
||||
let dicGoods = gameData.goods.get(id);
|
||||
let dicItid = ITID.get(dicGoods.itid);
|
||||
if(dicItid.table != 'jewel' && dicItid.table != 'artifact') {
|
||||
let index = result.findIndex(cur => cur.id == id);
|
||||
if(index == -1) {
|
||||
result.push({ id, count, seqId, isBag });
|
||||
} else {
|
||||
result[index].count += count;
|
||||
}
|
||||
} else {
|
||||
result.push({ id, count, seqId, isBag });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export function transPiece(hid: number) {
|
||||
let dicHero = gameData.hero.get(hid);
|
||||
let count = gameData.heroTransPiece.get(dicHero.quality);
|
||||
return { pieceId: dicHero.pieceId, count }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user