Files
ZYZ/game-server/app/services/equipService.ts
2022-02-17 12:41:40 +08:00

282 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { mergeSameGoods, getRandEelm, getRandValueByMinMax } from '../pubUtils/util';
import { EquipModel, RandMain } from "../db/Equip";
import { EPlace, HeroModel, HeroType, Stone } from "../db/Hero";
import { getGoodById, gameData, 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';
import { JewelType, RandSe } from '../db/Jewel';
import { getJewelRandSe } from '../pubUtils/itemUtils';
/**
* 校验前端传入的消耗数量是否准确并返回消耗的道具并加上特殊材料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 }[] = []
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 { randomEffect, effectCount } = gameData.jewel.get(id);
let chosen = randSe.filter(cur => cur.locked).map(cur => cur.seid); // 上一轮随机出来的
let randomResult: number[] = getRandEelm(randomEffect.filter(cur => !chosen.includes(cur)), effectCount); // 随机出的结果
if(randomResult.length < effectCount) { // 去上轮之后不够,把上轮加入
let chosenRandom = getRandEelm(chosen, effectCount - randomResult.length);
randomResult.push(...chosenRandom);
}
if(randomResult.length < effectCount) { // 还是不够
let allRandom = getRandEelm(randomEffect, effectCount - randomResult.length);
randomResult.push(...allRandom);
}
let newRandSe: RandSe[] = [];
for (let i = 0; i < effectCount; i++) {
if(randSe[i]) {
if(randSe[i] && randSe[i].locked) {
newRandSe.push(randSe[i]);
} else {
newRandSe.push(getJewelRandSe(randSe[i].id, randomResult[i]));
}
} else {
newRandSe.push(getJewelRandSe(i + 1, randomResult[i]));
}
}
return newRandSe
}
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
}
export function updateStone(origin: Stone[], id: number, target: number) {
let newStones: Stone[] = [];
let hasTarget = false;
for(let stone of origin) {
if(stone.id == id) {
newStones.push({ id, stone: target });
hasTarget = true;
} else {
newStones.push(stone);
}
}
if(!hasTarget) {
newStones.push({ id, stone: target });
}
return newStones;
}
export function updateEplace(eplace: EPlace[], eplaceId: number, update: Partial<EPlace>) {
let newEplace: EPlace[] = [];
let updatedEplace: Partial<EPlace>[] = [];
for(let equip of eplace) {
if(equip.id == eplaceId) {
newEplace.push({ ...equip, ...update });
updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update });
} else {
newEplace.push(equip);
}
}
return {newEplace, updatedEplace};
}
export function updateEplaces(eplace: EPlace[], update: Map<number, Partial<EPlace>>) {
let newEplace: EPlace[] = [];
let updatedEplace: Partial<EPlace>[] = [];
for(let equip of eplace) {
if(update.has(equip.id)) {
newEplace.push({ ...equip, ...update.get(equip.id) });
updatedEplace.push({ id: equip.id, equipId: equip.equipId, ...update.get(equip.id) });
} else {
newEplace.push(equip);
}
}
return {newEplace, updatedEplace};
}
/**
* 检查天晶石能否装备上这个装备
* @param equip
* @param jewel
*/
export function checkJewelCanPutOnEquip(equip: EPlace, jewel: JewelType) {
// 位置是否满足
let dicJewel = gameData.jewel.get(jewel.id);
if(!dicJewel || dicJewel.eplaceId != equip.id) return false;
// 品质是否满足
let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality);
if(!dicEquipQualityExtra || dicEquipQualityExtra.jewelCnt == 0) return false;
return true
}
export function checkStoneCanPutOnEquip(equip: EPlace, id: number, stone: number) {
if(stone == 0) return true; // 卸载
// 位置是否满足
let dicStone = gameData.stone.get(stone);
if(!dicStone || dicStone.eplaceId != equip.id) return false;
// 品质是否满足
let dicEquipQualityExtra = gameData.equipQualityExtra.get(equip.quality);
if(!dicEquipQualityExtra || dicEquipQualityExtra.stoneCnt < id) return false;
return true;
}