装备:淬火

This commit is contained in:
luying
2021-07-29 14:21:51 +08:00
parent dc832da60a
commit 972abb7d07
19 changed files with 805 additions and 68 deletions
@@ -10,13 +10,14 @@ import Role from "../../../db/Role";
import { calPlayerCeAndSave } from "../../../services/playerCeService"; import { calPlayerCeAndSave } from "../../../services/playerCeService";
import { getGoodById, gameData } from "../../../pubUtils/data"; import { getGoodById, gameData } from "../../../pubUtils/data";
import { EQUIP } from "../../../pubUtils/dicParam"; import { EQUIP } from "../../../pubUtils/dicParam";
import { ITID, SPEICAL_ITEM, QUALITY_TYPE, equipTypeToSortAttr, IT_TYPE } from "../../../consts/constModules/itemConst"; import { ITID, SPEICAL_ITEM, QUALITY_TYPE, equipTypeToSortAttr, IT_TYPE, QUENCH_TYPE } from "../../../consts";
import { changeEquip, dressEquip, checkMaterialEnough, takeOffEquipAndCalPlayerCe, checkEquipCanPut } from "../../../services/equipService"; import { changeEquip, dressEquip, checkMaterialEnough, takeOffEquipAndCalPlayerCe, checkEquipCanPut, quenchOnce, checkQuenchMaxByQualityAndGrade } from "../../../services/equipService";
import { findIndex } from 'underscore'; import { findIndex } from 'underscore';
import { pushEquipRefineSucMsg, pushNormalEquipMsg, pushNormalItemMsg } from "../../../services/chatService"; import { pushEquipRefineSucMsg, pushNormalEquipMsg, pushNormalItemMsg } from "../../../services/chatService";
import { checkTaskWithHero, checkTaskWithEquip, checkTask, checkTaskWithArgs, checkTaskConditionEquipSuitJewelStage, checkActivityTask } from "../../../services/taskService"; import { checkTaskWithHero, checkTaskWithEquip, checkTask, checkTaskWithArgs, checkTaskConditionEquipSuitJewelStage, checkActivityTask } from "../../../services/taskService";
import { Attribute } from "../../../domain/roleField/attribute"; import { Attribute } from "../../../domain/roleField/attribute";
import { QuenchLogParam } from "../../../domain/roleField/equip";
export default function (app: Application) { export default function (app: Application) {
new HandlerService(app, {}); new HandlerService(app, {});
@@ -459,6 +460,58 @@ export class EquipHandler {
} }
// 淬火
public async quench(msg: { eid: number, type: QUENCH_TYPE }, session: BackendSession) {
let roleId: string = session.get('roleId');
// let roleName: string = session.get('roleName');
let sid: string = session.get('sid');
let funcs: number[] = session.get('funcs');
let { eid, type } = msg;
let equip = await EquipModel.findbySeqId(eid);
if (!equip) return resResult(STATUS.EQUIP_NOT_FIND);
let { id, randMain, grade, hid, ePlaceId } = equip;
let dicGoods = gameData.goods.get(id);
if (!dicGoods) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let dicQuench = gameData.quench.get(grade);
if (!dicQuench) return resResult(STATUS.DIC_DATA_NOT_FOUND);
let logs: QuenchLogParam[] = [], times = 0;
while(
(type == QUENCH_TYPE.ONCE && times < 1 && !checkQuenchMaxByQualityAndGrade(dicGoods.quality, 0, randMain)) || // 淬火一次,保证不超出该品质上限
(type == QUENCH_TYPE.ONE_GRADE && !checkQuenchMaxByQualityAndGrade(dicGoods.quality, grade, randMain)) // 淬火一品,在品相上限内淬火
) {
let result = await quenchOnce(roleId, sid, randMain, dicQuench, dicGoods);
if(!result) break;
result.log.setTimes(++times);
logs.push(result.log);
grade = result.grade;
randMain = result.randMain;
}
if (times == 0) return resResult(STATUS.EQUIP_QUENCH_ERR);
let equipResult = await EquipModel.updateEquipInfo(eid, { randMain, grade })
let curEquip = {
seqId: equipResult.seqId,
id: equipResult.id,
randMain: equipResult.randMain,
grade: equipResult.grade,
}
// 更新战力
if(hid > 0) { // 装备中的时候
const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { });
}
return resResult(STATUS.SUCCESS, { logs, curEquip });
}
//分解装备 //分解装备
public async decomposeEquip(msg: { originalEquip: Array<number> }, session: BackendSession) { public async decomposeEquip(msg: { originalEquip: Array<number> }, session: BackendSession) {
let { originalEquip } = msg; let { originalEquip } = msg;
+86 -5
View File
@@ -1,13 +1,18 @@
import { mergeSameGoods, deepCopy } from '../pubUtils/util'; import { mergeSameGoods, getRandEelm } from '../pubUtils/util';
import { EquipModel } from "../db/Equip"; import { EquipModel, RandMain } from "../db/Equip";
import { HeroModel, EPlace, HeroType } from "../db/Hero"; import { HeroModel, HeroType } from "../db/Hero";
import { getHeroJob, getGoodById, gameData, getJewelById } from "../pubUtils/data"; import { getGoodById, gameData, getJewelById, getQuenchGradeByValue, getQuenchConsume, getQuenchByQualityAndGrade } from "../pubUtils/data";
import { calPlayerCeAndSave } from "./playerCeService"; import { calPlayerCeAndSave } from "./playerCeService";
import { HERO_SYSTEM_TYPE, TASK_TYPE } from "../consts"; import { HERO_SYSTEM_TYPE, TASK_TYPE } from "../consts";
import { EquipType } from "../db/Equip"; import { EquipType } from "../db/Equip";
import { calEquipSeids } from '../pubUtils/playerCe'; import { calEquipSeids } from '../pubUtils/playerCe';
import { indexOf, findIndex } from 'underscore';
import { checkTask, checkTaskWithHero, checkTaskWithEquip, checkActivityTask } from './taskService'; import { checkTask, checkTaskWithHero, checkTaskWithEquip, checkActivityTask } from './taskService';
import { DicQuench } from '../pubUtils/dictionary/DicQuench';
import { handleCost } from './rewardService';
import { DicGoods } from '../pubUtils/dictionary/DicGoods';
import { QuenchLogParam } from '../domain/roleField/equip';
import { QUENCH } from '../pubUtils/dicParam';
/** /**
* 校验前端传入的消耗数量是否准确,并返回消耗的道具并加上特殊材料needConsumes * 校验前端传入的消耗数量是否准确,并返回消耗的道具并加上特殊材料needConsumes
* @param consumes * @param consumes
@@ -139,3 +144,79 @@ export function checkEquipCanPut(hid: number, id: number) {
if(dicGood.charLimited != 0 && dicGood.charLimited != hid) return false; if(dicGood.charLimited != 0 && dicGood.charLimited != hid) return false;
return true return true
} }
/**
* 淬火一次
* @param roleId 玩家id
* @param sid 玩家sid
* @param randMain 装备上的属性随机值
* @param dicQuench 淬火表
* @param dicGoods 物品表
* @returns
*/
export async function quenchOnce(roleId: string, sid: string, randMain: RandMain[], dicQuench: DicQuench, dicGoods: DicGoods) {
let { quality, lvLimited } = 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(value/2);
// 消耗
let consumes = getQuenchConsume(lvLimited, quality);
let result = await handleCost(roleId, sid, consumes);
if(!result) return false;
let log = new QuenchLogParam(isCriticle, add);
return { randMain, grade, log };
}
/**
* 检查该品相是否到顶
* @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;
}
+2 -2
View File
@@ -196,7 +196,7 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
return showItems; return showItems;
} }
function sortItems(goods: Array<ItemInter>, bags: Array<BagInter>, skins: Array<number>, figures: Array<number>, currencysMap: any, equips: Array<EquipInter>, showItems: Array<ItemInter>) { function sortItems(goods: Array<ItemInter>, bags: Array<BagInter>, skins: Array<number>, figures: Array<number>, currencysMap: any, equips: EquipInter[], showItems: Array<ItemInter>) {
for (let good of goods) { for (let good of goods) {
let goodInfo = gameData.goods.get(good.id); let goodInfo = gameData.goods.get(good.id);
// 道具不存在时先跳过 // 道具不存在时先跳过
@@ -208,7 +208,7 @@ function sortItems(goods: Array<ItemInter>, bags: Array<BagInter>, skins: Array<
let { type, table, isCurrency } = ITID.get(goodInfo.itid); let { type, table, isCurrency } = ITID.get(goodInfo.itid);
if (table == ITEM_TABLE.EQUIP) { if (table == ITEM_TABLE.EQUIP) {
for (let i = 0; i < good.count; i++) { for (let i = 0; i < good.count; i++) {
equips.push({ id: good.id, ...goodInfo }); equips.push({ id: good.id });
} }
} else if (table == ITEM_TABLE.ITEM) { } else if (table == ITEM_TABLE.ITEM) {
+22 -22
View File
@@ -1,26 +1,26 @@
//武将养成系统分类 //武将养成系统分类
export const HERO_SYSTEM_TYPE = { export enum HERO_SYSTEM_TYPE {
INIT: 0, INIT = 0, // 初始武将
STAR: 1, STAR = 1, // 升星
LVUP: 2, LVUP = 2, // 升级
COLORSTAR: 3, COLORSTAR = 3, // 觉醒
QUALITY: 4, QUALITY = 4, // 升品
TRAIN: 5, TRAIN = 5, // (职业)训练
STAGEUP:6, STAGEUP =6, // (职业)升阶
SKIN:7, SKIN =7, // 皮肤
FAVOUR:8, FAVOUR =8, // 好感
CONNECT:9, CONNECT =9, // 羁绊
EQUIP: 10, EQUIP = 10, // 装备穿脱
EQUIP_BASE: 11, EQUIP_BASE = 11, // 装备栏升级,装备精炼等
RESTRENGTHEN: 12, RESTRENGTHEN = 12, // 洗练
JEWEL_ON: 13, JEWEL_ON = 13, // 穿宝石
JEWEL_OFF: 14, JEWEL_OFF = 14, // 脱宝石
ADD_SKIN: 15, ADD_SKIN = 15, // 第一次获取皮肤(全局)
SCHOOL: 16, SCHOOL = 16, // 百家学宫
SCROLL: 17, SCROLL = 17, // 名将谱
TITLE: 18, TITLE = 18, // 爵位
TERAPH: 19, TERAPH = 19, // 神像强化
TERAPH_UP: 20 TERAPH_UP = 20, // 神像升级
}; };
// 武将上限 // 武将上限
+6
View File
@@ -274,3 +274,9 @@ export const SPECIAL_ATTR = {
TREASURE_ID: 2, TREASURE_ID: 2,
TREASURE_TYPE: 3 TREASURE_TYPE: 3
} }
// 淬火类型
export enum QUENCH_TYPE {
ONCE = 1, // 升一级
ONE_GRADE = 2, // 升一品
}
+4 -1
View File
@@ -458,7 +458,10 @@ export const FILENAME = {
DIC_AP_BUY_COST: 'dic_zyz_daliyAP', DIC_AP_BUY_COST: 'dic_zyz_daliyAP',
DIC_GK_NEWHERO: 'dic_zyz_gk_newhero', DIC_GK_NEWHERO: 'dic_zyz_gk_newhero',
DIC_TASK_EXP: 'dic_zyz_mainTaskExp', DIC_TASK_EXP: 'dic_zyz_mainTaskExp',
DIC_GK_PROBATION: 'dic_zyz_gk_probation' DIC_GK_PROBATION: 'dic_zyz_gk_probation',
DIC_QUENCH: 'dic_zyz_quench',
DIC_QUENCH_QUALITY: 'dic_zyz_quench_quality',
DIC_QUENCH_CONSUME: 'dic_zyz_quench_consume',
} }
export const WAR_RELATE_TABLES = [ export const WAR_RELATE_TABLES = [
+1
View File
@@ -277,6 +277,7 @@ export const STATUS = {
EQUIP_NOT_EQUIPED_HERO: { code: 30509, simStr: '装备不能被该武将穿戴' }, EQUIP_NOT_EQUIPED_HERO: { code: 30509, simStr: '装备不能被该武将穿戴' },
EQUIP_LEVEL_LIMIT: { code: 30510, simStr: '装备穿戴等级限制' }, EQUIP_LEVEL_LIMIT: { code: 30510, simStr: '装备穿戴等级限制' },
EQUIP_NOT_MATCH_JEWEL: { code: 30511, simStr: '装备不能镶嵌该宝石' }, EQUIP_NOT_MATCH_JEWEL: { code: 30511, simStr: '装备不能镶嵌该宝石' },
EQUIP_QUENCH_ERR: { code: 30512, simStr: '该装备不能再淬火或材料不足' },
//全局养成30600-30699 //全局养成30600-30699
ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' }, ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' },
ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '玩家神像不能强化' }, ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '玩家神像不能强化' },
+15 -13
View File
@@ -24,14 +24,11 @@ export class Holes {
jewel: number; // 装备的宝石id jewel: number; // 装备的宝石id
} }
interface equipUpdate { export class RandMain {
hid?: number; @prop({ required: true })
quality?: number; id: number; // 随机属性位置id
wearLv?: number; @prop({ required: true })
_id?: number; rand: number; // 随机属性内需要随机的值,扩大100倍
holes?: Array<Holes>;
randSe?: Array<RandSe>;
ePlaceId?: number;
} }
@index({ roleId: 1, hid: 1, id: 1 }) @index({ roleId: 1, hid: 1, id: 1 })
@@ -51,7 +48,7 @@ export default class Equip extends BaseModel {
@prop({ required: true }) @prop({ required: true })
name: string; // 装备名称 name: string; // 装备名称
@prop({ required: false, default: 0 }) @prop({ required: false, default: 0 })
hid: number; // 装备此装备的武将 id hid: number; // 装备此装备的武将 id
@prop({ required: false, default: 0 }) @prop({ required: false, default: 0 })
ePlaceId: number; // 武将装备的部位 ePlaceId: number; // 武将装备的部位
@prop({ required: false, default: 1 }) @prop({ required: false, default: 1 })
@@ -60,12 +57,16 @@ export default class Equip extends BaseModel {
@prop({ required: true, default: 1 }) @prop({ required: true, default: 1 })
quality: number; // 品质 quality: number; // 品质
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
suitId: number; // 套装id suitId: number; // 套装id
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
randRange: number; // 固定属性随机值 randRange: number; // 固定属性随机值 // TODO 废弃字段,客户端改完之前暂时保留
@prop({ required: false, type: RandMain, default: [], _id: false })
randMain: RandMain[]; // 主属性随机
@prop({ required: true, default: 0 })
grade: number; // 品相等级
@prop({ required: false, type: RandSe, default: [], _id: false }) @prop({ required: false, type: RandSe, default: [], _id: false })
randSe: RandSe[]; // 强化随机属性 randSe: RandSe[]; // 强化随机属性
@prop({ required: true, type: Holes, default: [], _id: false }) @prop({ required: true, type: Holes, default: [], _id: false })
holes: Holes[]; holes: Holes[];
@@ -79,7 +80,7 @@ export default class Equip extends BaseModel {
return equip; return equip;
} }
public static async createEquip(equipInfo: { roleId: string, roleName: string, id: number, name: string, quality: number, suitId: number, ePlaceId: number, randSe: RandSe[], randRange: number, holes: Holes[], hid?: number }, lean = true) { public static async createEquip(equipInfo: equipUpdate, lean = true) {
const seqId = await CounterModel.getNewCounter(COUNTER.EID); const seqId = await CounterModel.getNewCounter(COUNTER.EID);
const doc = new EquipModel(); const doc = new EquipModel();
@@ -183,3 +184,4 @@ export const EquipModel = getModelForClass(Equip);
export interface EquipType extends Pick<DocumentType<Equip>, keyof Equip> { export interface EquipType extends Pick<DocumentType<Equip>, keyof Equip> {
id: number; id: number;
}; };
export type equipUpdate = Partial<EquipType>; // 将所有字段变成可选项
+25
View File
@@ -0,0 +1,25 @@
interface QuenchAddParam {
id: number; // 属性id
value: number; // 增加的值
}
export class QuenchLogParam {
times: number; // 第几次
isCriticle: boolean; // 是否暴击
add: QuenchAddParam[];
constructor(isCriticle: boolean, add: Map<number, number>) {
this.isCriticle = isCriticle;
let arr: QuenchAddParam[] = [];
for(let [id, value] of add) {
arr.push({ id, value });
}
this.add = arr;
}
setTimes(times: number) {
this.times = times;
}
}
+40 -1
View File
@@ -88,6 +88,9 @@ import { dicServerName, dicServerGroupName, loadServerName } from "./dictionary/
import { dicAp, loadAp, dicApMaxLevel } from './dictionary/DicAp'; import { dicAp, loadAp, dicApMaxLevel } from './dictionary/DicAp';
import { dicApBuy, dicApMaxBuyTimes, loadApBuy } from "./dictionary/DicApBuy"; import { dicApBuy, dicApMaxBuyTimes, loadApBuy } from "./dictionary/DicApBuy";
import { dicTaskExp, loadTskExp} from './dictionary/DicTaskExp'; import { dicTaskExp, loadTskExp} from './dictionary/DicTaskExp';
import { dicQuench, loadQuench } from './dictionary/DicQuench';
import { dicQuenchByQuality, dicQuenchByQualityAndGrade, loadQuenchQuality } from './dictionary/DicQuenchQuality';
import { dicQuenchConsume, loadQuenchConsume } from './dictionary/DicQuenchConsume';
export const gameData = { export const gameData = {
blurprtCompose: dicBlueprtCompose, blurprtCompose: dicBlueprtCompose,
@@ -216,7 +219,11 @@ export const gameData = {
apMaxLevel: dicApMaxLevel, apMaxLevel: dicApMaxLevel,
apBuy: dicApBuy, apBuy: dicApBuy,
apMaxBuyTimes: dicApMaxBuyTimes, apMaxBuyTimes: dicApMaxBuyTimes,
taskExp: dicTaskExp taskExp: dicTaskExp,
quench: dicQuench,
quenchByQuality: dicQuenchByQuality,
quenchByQualityAndGrade: dicQuenchByQualityAndGrade,
quenchConsume: dicQuenchConsume
}; };
// 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据 // 在此提供一些原先在gamedata中提供的方法,以便更方便获取gameData数据
@@ -723,6 +730,34 @@ export function getDicSuitByTypeAndLv(suitType: number, starLevel: number) {
return gameData.suitByTypeAndLv.get(`${suitType}_${starLevel}`); return gameData.suitByTypeAndLv.get(`${suitType}_${starLevel}`);
} }
export function getQuenchGradeByValue(value: number) {
let grade = 0;
for(let [_grade, { singleRatioMin, singleRatioMax }] of gameData.quench) {
if(value >= singleRatioMin && value < singleRatioMax ) {
grade = _grade;
}
}
return grade;
}
/**
* 根绝品质和品相获得上下限,当grade为0,获取该品质下全阶的上下限
* @param quality 品质
* @param grade 品相
* @returns {{ min: number, max: number }}
*/
export function getQuenchByQualityAndGrade(quality: number, grade: number) {
if(grade == 0) { // 这个品质的上下限
return gameData.quenchByQuality.get(quality);
} else { // 该品质该品相的上下限
return gameData.quenchByQualityAndGrade.get(`${quality}_${grade}`);
}
}
export function getQuenchConsume(lvLimited: number, quality: number) {
return gameData.quenchConsume.get(`${lvLimited}_${quality}`);
}
// 初始加载 // 初始加载
function initDatas() { function initDatas() {
parseDicParam(); parseDicParam();
@@ -824,6 +859,10 @@ function loadDatas() {
loadAp(); loadAp();
loadApBuy(); loadApBuy();
loadTskExp(); loadTskExp();
loadQuench();
loadQuenchQuality();
loadQuenchConsume();
} }
// 重载dicParam // 重载dicParam
+29
View File
@@ -0,0 +1,29 @@
import { readFileAndParse } from '../util'
import { FILENAME } from '../../consts'
export interface DicQuench {
// id
readonly id: number;
// 品相
readonly grade: number;
// 品相名
readonly name: string;
// 单属性最小值
readonly singleRatioMin: number;
// 单属性最大值
readonly singleRatioMax: number;
// 暴击效果,倍率
readonly critEffect: number;
// 暴击概率
readonly critProbability: number;
}
export const dicQuench = new Map<number, DicQuench>(); // id => dic
export function loadQuench() {
let arr = readFileAndParse(FILENAME.DIC_QUENCH);
arr.forEach(o => {
dicQuench.set(o.grade, o);
});
arr = undefined;
}
@@ -0,0 +1,25 @@
import { readFileAndParse, parseGoodStr } from '../util'
import { FILENAME } from '../../consts'
import { RewardInter } from '../interface';
export interface DicQuenchConsume {
// id
readonly id: number;
// 等级
readonly equipLvl: number;
// 品质
readonly quality: number;
// 淬火一次的消耗
readonly unitConsume: RewardInter[];
}
export const dicQuenchConsume = new Map<string, RewardInter[]>(); // equipLvl&quality => dic
export function loadQuenchConsume() {
let arr = readFileAndParse(FILENAME.DIC_QUENCH_CONSUME);
arr.forEach(o => {
o.unitConsume = parseGoodStr(o.unitconsume);
dicQuenchConsume.set(`${o.equipLvl}_${o.quality}`, o.unitConsume);
});
arr = undefined;
}
@@ -0,0 +1,42 @@
import { readFileAndParse, parseGoodStr } from '../util'
import { FILENAME } from '../../consts'
export interface DicQuenchQuality {
// id
readonly id: number;
// 装备品质
readonly quality: number;
// 品相
readonly grade: number;
// 单属性最小值
readonly singleRatioMin: number;
// 单属性最大值
readonly singleRatioMax: number;
// 初始是否可以随机出
readonly initialAvailable: number;
}
export const dicQuenchByQualityAndGrade = new Map<string, { min: number, max: number }>();
export const dicQuenchByQuality = new Map<number, { min: number, max: number }>(); // quality => {}
export function loadQuenchQuality() {
dicQuenchByQuality.clear();
dicQuenchByQualityAndGrade.clear();
let arr = readFileAndParse(FILENAME.DIC_QUENCH_QUALITY);
arr.forEach(o => {
if(o.initialAvailable == 1) {
if(!dicQuenchByQuality.has(o.quality)) {
dicQuenchByQuality.set(o.quality, { min: o.singleRatioMin, max: o.singleRatioMax });
} else {
if(o.singleRatioMin < dicQuenchByQuality.get(o.quality).min) {
dicQuenchByQuality.get(o.quality).min = o.singleRatioMin;
}
if(o.singleRatioMax > dicQuenchByQuality.get(o.quality).max) {
dicQuenchByQuality.get(o.quality).max = o.singleRatioMax;
}
}
dicQuenchByQualityAndGrade.set(`${o.quality}_${o.grade}`, { min: o.singleRatioMin, max: o.singleRatioMax });
}
});
arr = undefined;
}
-6
View File
@@ -9,12 +9,6 @@ export interface RewardInter {
export interface EquipInter { export interface EquipInter {
id: number; id: number;
name: string;
quality: number;
suitId: number;
hole: number;
randomEffect: Array<number>;
itid: number;
hid?: number; hid?: number;
times?: number; times?: number;
}; };
+24 -6
View File
@@ -2,9 +2,9 @@
import { HeroModel, HeroType } from '../db/Hero'; import { HeroModel, HeroType } from '../db/Hero';
import { ItemModel } from '../db/Item'; import { ItemModel } from '../db/Item';
import { EquipModel, RandSe, Holes } from './../db/Equip'; import { EquipModel, RandSe, Holes, RandMain } from './../db/Equip';
import { BagInter, EquipInter } from './interface'; import { BagInter, EquipInter } from './interface';
import { gameData } from './data'; import { gameData, getQuenchByQualityAndGrade, getQuenchGradeByValue } from './data';
import { RANDOM_SE_COUNT, FIX_ATTRIBUTES_RAN, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, CONSUME_TYPE, HERO_SYSTEM_TYPE, TASK_TYPE } from '../consts'; import { RANDOM_SE_COUNT, FIX_ATTRIBUTES_RAN, ITID, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_SELECT, FIGURE_UNLOCK_CONDITION, CONSUME_TYPE, HERO_SYSTEM_TYPE, TASK_TYPE } from '../consts';
import { getRandValueByMinMax, getRandEelm } from './util'; import { getRandValueByMinMax, getRandEelm } from './util';
@@ -55,9 +55,11 @@ export async function addBags(roleId: string, roleName: string, data: BagInter)
} }
export async function addEquips(roleId: string, roleName: string, weapon: EquipInter) { export async function addEquips(roleId: string, roleName: string, weapon: EquipInter) {
let { id, name, quality, suitId, hole, randomEffect, itid, hid } = weapon; let { id, hid = 0 } = weapon;
let { name, quality, suitId, hole, randomEffect, itid, goodsAbility } = gameData.goods.get(id);
let { type } = ITID.get(itid); let { type } = ITID.get(itid);
// 随机属性
let randomNum = RANDOM_SE_COUNT.get(quality); let randomNum = RANDOM_SE_COUNT.get(quality);
let randomResult: number[] = getRandEelm(randomEffect, randomNum); let randomResult: number[] = getRandEelm(randomEffect, randomNum);
@@ -73,14 +75,30 @@ export async function addEquips(roleId: string, roleName: string, weapon: EquipI
}; };
}); });
let randRange = getRandValueByMinMax(0 - FIX_ATTRIBUTES_RAN, FIX_ATTRIBUTES_RAN, 0); let randRange = 0;
// 淬火品相
let randMain: RandMain[] = [];
let grade = 0;
for(let [ attrId, attrValue ] of goodsAbility) {
if(attrValue > 0) {
let { min, max } = getQuenchByQualityAndGrade(quality, grade);
let rand = getRandValueByMinMax(min, max, 0);
grade = getQuenchGradeByValue(rand);
randMain.push({
id: attrId,
rand
});
}
}
let holes = new Array<Holes>(); let holes = new Array<Holes>();
for (let i = 0; i < hole; i++) { for (let i = 0; i < hole; i++) {
holes.push({ id: i + 1, isOpen: false, jewel: 0 }) holes.push({ id: i + 1, isOpen: false, jewel: 0 });
} }
const equip = await EquipModel.createEquip({ roleId, roleName, id, name, quality, suitId, randRange, ePlaceId: type, randSe, holes, hid }); const equip = await EquipModel.createEquip({ roleId, roleName, id, name, quality, suitId, randRange, ePlaceId: type, randSe, holes, hid, grade, randMain });
// 任务 // 任务
let pushMessage = await checkTaskWithEquip(roleId, TASK_TYPE.EQUIP_SUIT, equip); let pushMessage = await checkTaskWithEquip(roleId, TASK_TYPE.EQUIP_SUIT, equip);
+11 -9
View File
@@ -695,11 +695,8 @@ export function calEquipSeids(hero: HeroType) {
} }
} }
} }
console.log('################')
console.log('#####1', JSON.stringify([...suits]));
for(let [ _suitType, map ] of suits) { for(let [ _suitType, map ] of suits) {
console.log('#####2', _suitType, JSON.stringify([...map]));
let effectSeid = new Map<number, { starLevel: number, seid: number }>(); // count => { starLevel, seid } let effectSeid = new Map<number, { starLevel: number, seid: number }>(); // count => { starLevel, seid }
for(let [ starLevel, { dic: { effect }, count } ] of map) { for(let [ starLevel, { dic: { effect }, count } ] of map) {
for(let { count: effectCount, seid} of effect) { for(let { count: effectCount, seid} of effect) {
@@ -713,7 +710,6 @@ export function calEquipSeids(hero: HeroType) {
for(let [_count, { seid }] of effectSeid) { for(let [_count, { seid }] of effectSeid) {
seids.push(seid, 0); seids.push(seid, 0);
} }
console.log('#####3', _suitType, JSON.stringify([...effectSeid]));
} }
return seids; return seids;
} }
@@ -750,6 +746,10 @@ export function calHeroEquipIncAttr(hero: HeroType) {
} }
} }
let randMainMap = new Map<number, number>();
for(let {id, rand} of (e.randMain||[])) {
randMainMap.set(id, rand);
}
for (let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) { for (let i = ABI_TYPE.ABI_HP; i < ABI_TYPE.ABI_MAX; i++) {
// console.log('***', i); // console.log('***', i);
let value1 = goodsAbility.get(i) || 0 * (HERO_CE_RATIO + e.randRange); let value1 = goodsAbility.get(i) || 0 * (HERO_CE_RATIO + e.randRange);
@@ -757,17 +757,19 @@ export function calHeroEquipIncAttr(hero: HeroType) {
let valueup = goodsAbilityUp.get(i) || 0; let valueup = goodsAbilityUp.get(i) || 0;
// console.log('成长', lv, valueup); // console.log('成长', lv, valueup);
let valueRefine = dicRefine ? dicRefine.upPercent : 0; let valueRefine = dicRefine ? dicRefine.upPercent : 0;
// console.log('refine', dicRefine?dicRefine.upPercent:0 ); // console.log('精炼', dicRefine?dicRefine.upPercent:0 );
let valueJewel = jewel.get(i) || 0; let valueJewel = jewel.get(i) || 0;
// console.log('jewel', valueJewel); // console.log('宝石', valueJewel);
let attr = (value1 + lv * valueup) * (HERO_CE_RATIO + valueRefine) + valueJewel * HERO_CE_RATIO; let valueGrade = randMainMap.get(i)||0;
// console.log('品相', valueGrade)
let attr = (value1 + lv * valueup) * valueGrade * (HERO_CE_RATIO + valueRefine) + valueJewel * HERO_CE_RATIO * HERO_CE_RATIO;
if(attr >= 0) { if(attr >= 0) {
// console.log('装备战力:', i, attr); // console.log('装备战力:', i, attr);
if(setMap.has(i)) { if(setMap.has(i)) {
setMap.set(i, setMap.get(i) + attr); setMap.set(i, setMap.get(i) + Math.floor(attr / HERO_CE_RATIO));
} else { } else {
setMap.set(i, attr); setMap.set(i, Math.floor(attr / HERO_CE_RATIO));
} }
} }
} }
+98
View File
@@ -0,0 +1,98 @@
[
{
"id": 1,
"grade": 1,
"name": "残品",
"singleRatioMin": 30,
"singleRatioMax": 40,
"quality": "1&",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 2,
"grade": 2,
"name": "次品",
"singleRatioMin": 40,
"singleRatioMax": 50,
"quality": "1&2",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 3,
"grade": 3,
"name": "凡品",
"singleRatioMin": 50,
"singleRatioMax": 60,
"quality": "1&2&3",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 4,
"grade": 4,
"name": "良品",
"singleRatioMin": 60,
"singleRatioMax": 70,
"quality": "2&3&4",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 5,
"grade": 5,
"name": "精品",
"singleRatioMin": 70,
"singleRatioMax": 80,
"quality": "3&4&5",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 6,
"grade": 6,
"name": "极品",
"singleRatioMin": 80,
"singleRatioMax": 90,
"quality": "4&5",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 1
},
{
"id": 7,
"grade": 7,
"name": "圣品",
"singleRatioMin": 90,
"singleRatioMax": 100,
"quality": "5&",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 0
},
{
"id": 8,
"grade": 8,
"name": "神品",
"singleRatioMin": 100,
"singleRatioMax": 0,
"quality": "5&",
"unitConsume": 0,
"critEffect": 2,
"critProbability": 20,
"initialAvailable": 0
}
]
@@ -0,0 +1,182 @@
[
{
"id": 1,
"equipLvl": 1,
"quality": 1,
"unitconsume": "17051&1"
},
{
"id": 2,
"equipLvl": 1,
"quality": 2,
"unitconsume": "17051&2"
},
{
"id": 3,
"equipLvl": 1,
"quality": 3,
"unitconsume": "17051&3"
},
{
"id": 4,
"equipLvl": 1,
"quality": 4,
"unitconsume": "17051&4"
},
{
"id": 5,
"equipLvl": 1,
"quality": 5,
"unitconsume": "17051&5"
},
{
"id": 6,
"equipLvl": 2,
"quality": 1,
"unitconsume": "17051&2"
},
{
"id": 7,
"equipLvl": 2,
"quality": 2,
"unitconsume": "17051&4"
},
{
"id": 8,
"equipLvl": 2,
"quality": 3,
"unitconsume": "17051&6"
},
{
"id": 9,
"equipLvl": 2,
"quality": 4,
"unitconsume": "17051&8"
},
{
"id": 10,
"equipLvl": 2,
"quality": 5,
"unitconsume": "17051&10"
},
{
"id": 11,
"equipLvl": 3,
"quality": 1,
"unitconsume": "17051&4"
},
{
"id": 12,
"equipLvl": 3,
"quality": 2,
"unitconsume": "17051&8"
},
{
"id": 13,
"equipLvl": 3,
"quality": 3,
"unitconsume": "17051&12"
},
{
"id": 14,
"equipLvl": 3,
"quality": 4,
"unitconsume": "17051&16"
},
{
"id": 15,
"equipLvl": 3,
"quality": 5,
"unitconsume": "17051&20"
},
{
"id": 16,
"equipLvl": 4,
"quality": 1,
"unitconsume": "17051&8"
},
{
"id": 17,
"equipLvl": 4,
"quality": 2,
"unitconsume": "17051&16"
},
{
"id": 18,
"equipLvl": 4,
"quality": 3,
"unitconsume": "17051&24"
},
{
"id": 19,
"equipLvl": 4,
"quality": 4,
"unitconsume": "17051&32"
},
{
"id": 20,
"equipLvl": 4,
"quality": 5,
"unitconsume": "17051&40"
},
{
"id": 21,
"equipLvl": 5,
"quality": 1,
"unitconsume": "17051&16"
},
{
"id": 22,
"equipLvl": 5,
"quality": 2,
"unitconsume": "17051&32"
},
{
"id": 23,
"equipLvl": 5,
"quality": 3,
"unitconsume": "17051&48"
},
{
"id": 24,
"equipLvl": 5,
"quality": 4,
"unitconsume": "17051&64"
},
{
"id": 25,
"equipLvl": 5,
"quality": 5,
"unitconsume": "17051&80"
},
{
"id": 26,
"equipLvl": 6,
"quality": 1,
"unitconsume": "17051&64"
},
{
"id": 27,
"equipLvl": 6,
"quality": 2,
"unitconsume": "17051&128"
},
{
"id": 28,
"equipLvl": 6,
"quality": 3,
"unitconsume": "17051&192"
},
{
"id": 29,
"equipLvl": 6,
"quality": 4,
"unitconsume": "17051&256"
},
{
"id": 30,
"equipLvl": 6,
"quality": 5,
"unitconsume": "17051&320"
}
]
@@ -0,0 +1,137 @@
[
{
"id": 1,
"quality": 1,
"grade": 1,
"name": "残品",
"singleRatioMin": 30,
"singleRatioMax": 40,
"initialAvailable": 1
},
{
"id": 2,
"quality": 1,
"grade": 2,
"name": "次品",
"singleRatioMin": 40,
"singleRatioMax": 50,
"initialAvailable": 1
},
{
"id": 3,
"quality": 1,
"grade": 3,
"name": "凡品",
"singleRatioMin": 50,
"singleRatioMax": 50,
"initialAvailable": 1
},
{
"id": 4,
"quality": 2,
"grade": 2,
"name": "次品",
"singleRatioMin": 40,
"singleRatioMax": 50,
"initialAvailable": 1
},
{
"id": 5,
"quality": 2,
"grade": 3,
"name": "凡品",
"singleRatioMin": 50,
"singleRatioMax": 60,
"initialAvailable": 1
},
{
"id": 6,
"quality": 2,
"grade": 4,
"name": "良品",
"singleRatioMin": 60,
"singleRatioMax": 60,
"initialAvailable": 1
},
{
"id": 7,
"quality": 3,
"grade": 3,
"name": "凡品",
"singleRatioMin": 50,
"singleRatioMax": 60,
"initialAvailable": 1
},
{
"id": 8,
"quality": 3,
"grade": 4,
"name": "良品",
"singleRatioMin": 60,
"singleRatioMax": 70,
"initialAvailable": 1
},
{
"id": 9,
"quality": 3,
"grade": 5,
"name": "精品",
"singleRatioMin": 70,
"singleRatioMax": 70,
"initialAvailable": 1
},
{
"id": 10,
"quality": 4,
"grade": 4,
"name": "良品",
"singleRatioMin": 60,
"singleRatioMax": 70,
"initialAvailable": 1
},
{
"id": 11,
"quality": 4,
"grade": 5,
"name": "精品",
"singleRatioMin": 70,
"singleRatioMax": 80,
"initialAvailable": 1
},
{
"id": 12,
"quality": 4,
"grade": 6,
"name": "极品",
"singleRatioMin": 80,
"singleRatioMax": 80,
"initialAvailable": 1
},
{
"id": 13,
"quality": 5,
"grade": 6,
"name": "极品",
"singleRatioMin": 80,
"singleRatioMax": 90,
"initialAvailable": 1
},
{
"id": 14,
"quality": 5,
"grade": 7,
"name": "圣品",
"singleRatioMin": 90,
"singleRatioMax": 100,
"initialAvailable": 0
},
{
"id": 15,
"quality": 5,
"grade": 8,
"name": "神品",
"singleRatioMin": 100,
"singleRatioMax": 100,
"initialAvailable": 0
}
]