200 lines
7.4 KiB
TypeScript
200 lines
7.4 KiB
TypeScript
import { mergeSameGoods, getRandEelm, getRandValueByMinMax } from '../pubUtils/util';
|
||
import { EquipModel, RandMain, RandSe } from "../db/Equip";
|
||
import { HeroModel, HeroType } from "../db/Hero";
|
||
import { getGoodById, gameData, getJewelById, getQuenchGradeByValue, getQuenchConsume, getQuenchByQualityAndGrade } from "../pubUtils/data";
|
||
import { calPlayerCeAndSave } from "./playerCeService";
|
||
import { CONSUME_TYPE, HERO_SYSTEM_TYPE, ITID, TASK_TYPE } from "../consts";
|
||
import { dicGoods, DicGoods } from '../pubUtils/dictionary/DicGoods';
|
||
import { QuenchLogParam } from '../domain/roleField/equip';
|
||
import { QUENCH } from '../pubUtils/dicParam';
|
||
import { DicQuenchQuality } from '../pubUtils/dictionary/DicQuenchQuality';
|
||
|
||
/**
|
||
* 校验前端传入的消耗数量是否准确,并返回消耗的道具并加上特殊材料needConsumes
|
||
* @param consumes
|
||
* @param jewel
|
||
* @param jewelCount
|
||
*/
|
||
export function checkMaterialEnough(consumes: Array<{ id: number, count: number }>, jewel: number, jewelCount: number) {
|
||
let comJewelMap = new Map<number, number>(); // good_id => count
|
||
let needConsumes:{ id: number, count: number, ratio?: number }[] = []
|
||
for(let {id, count} of consumes) {
|
||
if(!comJewelMap.has(id)) {
|
||
comJewelMap.set(id, count);
|
||
} else {
|
||
comJewelMap.set(id, comJewelMap.get(id) + count);
|
||
}
|
||
}
|
||
|
||
function checkCurMeterial(target: number, targetCount: number) {
|
||
let dic = getGoodById(target);
|
||
if(!dic) return false;
|
||
let { composeMaterial } = dic;
|
||
|
||
let isEnough = true;
|
||
for(let { id, count } of composeMaterial) {
|
||
let consumeCount = comJewelMap.get(id)||0;
|
||
let dicGood = getGoodById(id);
|
||
if(!dicGoods) { isEnough = false; break; }
|
||
let dicItid = ITID.get(dicGood.itid);
|
||
if(dicItid.type != CONSUME_TYPE.JEWEL) {
|
||
if(consumeCount < count * targetCount) {
|
||
isEnough = false; break;
|
||
} else {
|
||
comJewelMap.set(id, consumeCount - count * targetCount);
|
||
needConsumes.push({ id, count: count * targetCount });
|
||
}
|
||
} else {
|
||
if(consumeCount < count * targetCount) {
|
||
comJewelMap.set(id, 0);
|
||
needConsumes.push({ id, count: consumeCount });
|
||
isEnough = checkCurMeterial(id, count * targetCount - consumeCount);
|
||
} else {
|
||
comJewelMap.set(id, consumeCount - count * targetCount);
|
||
needConsumes.push({ id, count: count * targetCount });
|
||
}
|
||
|
||
}
|
||
}
|
||
return isEnough
|
||
}
|
||
|
||
let isEnough = checkCurMeterial(jewel, jewelCount);
|
||
return isEnough? needConsumes: false;
|
||
}
|
||
|
||
export function checkEquipCanPut(hero: HeroType, id: number) {
|
||
let hid = hero.skinId;
|
||
let dicGood = gameData.goods.get(id);
|
||
if(dicGood.lvLimited > hero.lv) return false;
|
||
let dicHero = gameData.hero.get(hid);
|
||
if(dicGood.jobLimited.indexOf(0) == -1 && dicGood.jobLimited.indexOf(dicHero.jobClass) == -1) return false;
|
||
if(dicGood.charLimited.indexOf(0) == -1 && dicGood.charLimited.indexOf(hid) == -1) return false;
|
||
return true
|
||
}
|
||
|
||
|
||
/**
|
||
* 淬火一次
|
||
* @param roleId 玩家id
|
||
* @param sid 玩家sid
|
||
* @param randMain 装备上的属性随机值
|
||
* @param dicQuench 淬火表
|
||
* @param dicGoods 物品表
|
||
* @returns
|
||
*/
|
||
export async function quenchOnce(randMain: RandMain[], dicQuench: DicQuenchQuality, dicGoods: DicGoods) {
|
||
let { quality, equipLvl } = dicGoods;
|
||
|
||
let canRandMain = randMain.filter(cur => { // 已升满的属性就不再淬火了
|
||
return cur.rand < dicQuench.singleRatioMax;
|
||
});
|
||
let randMainResult = getRandEelm(canRandMain);
|
||
if(randMainResult.length == 0) return false;
|
||
|
||
let add = new Map<number, number>(); // id => value,增加的数量
|
||
let isCriticle = Math.random() * 100 < dicQuench.critProbability; // 暴击
|
||
let addAttr = isCriticle? dicQuench.critEffect * QUENCH.QUENCH_UNIT_UPRATIO: QUENCH.QUENCH_UNIT_UPRATIO;
|
||
let overAttr = randMainResult[0].rand + addAttr - dicQuench.singleRatioMax; // 如果有暴击,超出当前品相上限时
|
||
if(overAttr > 0) { // 超出,转到另一条属性
|
||
let anotherRandMain = canRandMain.filter(cur => {
|
||
return cur.id != randMainResult[0].id;
|
||
});
|
||
if(anotherRandMain.length > 0) {
|
||
let anotherOverAttr = anotherRandMain[0].rand + overAttr - dicQuench.singleRatioMax;
|
||
if(anotherOverAttr > 0) {
|
||
add.set(anotherRandMain[0].id, overAttr - anotherOverAttr);
|
||
} else {
|
||
add.set(anotherRandMain[0].id, overAttr);
|
||
}
|
||
}
|
||
add.set(randMainResult[0].id, addAttr - overAttr);
|
||
} else {
|
||
add.set(randMainResult[0].id, addAttr);
|
||
}
|
||
|
||
let value = 0;
|
||
for(let r of randMain) {
|
||
if(add.has(r.id)) {
|
||
r.rand += add.get(r.id);
|
||
}
|
||
value += r.rand;
|
||
}
|
||
let grade = getQuenchGradeByValue(quality, value/2);
|
||
|
||
// 消耗
|
||
let consumes = getQuenchConsume(equipLvl, quality);
|
||
|
||
let log = new QuenchLogParam(isCriticle, add);
|
||
return { randMain, grade, log, consumes };
|
||
}
|
||
|
||
/**
|
||
* 检查该品相是否到顶
|
||
* @param quality 品质
|
||
* @param grade 品相
|
||
* @param randMain 装备上的随机值
|
||
* @returns
|
||
*/
|
||
export function checkQuenchMaxByQualityAndGrade(quality: number, grade: number, randMain: RandMain[]) {
|
||
let isMax = true;
|
||
let dic = getQuenchByQualityAndGrade(quality, grade);
|
||
if(!dic) return true;
|
||
for(let { rand } of randMain) {
|
||
if(rand < dic.max) isMax = false;
|
||
}
|
||
return isMax;
|
||
}
|
||
|
||
export function getRandSeResult(id: number, randSe: RandSe[]) {
|
||
let dicGoods = gameData.goods.get(id);
|
||
if (!dicGoods) return false;
|
||
|
||
let { randomEffect } = dicGoods; // 配置的可随机seid
|
||
let chosen = randSe.filter(cur => cur.locked).map(cur => cur.seid); // 上一轮随机出来的
|
||
let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), randSe.length); // 随机出的结果
|
||
|
||
for (let i = 0; i < randSe.length; i++) {
|
||
if (!randSe[i].locked) {
|
||
let random = gameData.randomEffectPool.get(randomResult[i]);
|
||
if (!random) break;
|
||
let rand = 0;
|
||
if (random.id > 0) rand = getRandValueByMinMax(random.Min, random.Max, 0);
|
||
randSe[i].seid = random.id;
|
||
randSe[i].rand = rand;
|
||
}
|
||
}
|
||
return randSe
|
||
}
|
||
|
||
export async function refineOnce(lv: number, refineLv: number) {
|
||
|
||
let dicRefine = gameData.refine.get(refineLv + 1);
|
||
if (!dicRefine) return false;
|
||
|
||
if(lv < dicRefine.levelLimited) return false;
|
||
|
||
return {
|
||
refineLv: refineLv + 1,
|
||
consumes: dicRefine.consume
|
||
}
|
||
}
|
||
|
||
export function checkRefineReachNextLv(oldRefineLv: number, refineLv: number) {
|
||
let oldDic = gameData.refine.get(oldRefineLv);
|
||
let dic = gameData.refine.get(refineLv);
|
||
if(!oldDic || !dic) return true;
|
||
|
||
return dic.level > oldDic.level;
|
||
}
|
||
|
||
export function calEquipCe(goodsAbility: Map<number, number>, randMain: RandMain[]) {
|
||
let ce = 0;
|
||
for(let [ id, ratio ] of gameData.equipAttributeRatio) {
|
||
let valueBase = goodsAbility.get(id);
|
||
let curRand = randMain.find(cur => cur.id == id);
|
||
let valueRand = curRand?curRand.rand: 0;
|
||
ce += Math.floor(valueBase * valueRand * ratio / 100);
|
||
}
|
||
return ce
|
||
} |