mirror of
https://github.com/yoimiya-kokomi/miao-plugin.git
synced 2024-11-25 09:27:34 +00:00
#更新全部面板
一些已知问题修复
* 目前可正确获取圣遗物名称了,`#圣遗物列表`如有错误重新获角色信息后即正常 * 雷神、莫娜的元素伤害字段数据错误fix * 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
This commit is contained in:
parent
0608ca697b
commit
9b90010daa
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,11 +1,14 @@
|
||||
# 1.6.4
|
||||
# 1.6.5
|
||||
|
||||
* `#更新全部面板` 一些已知问题修复
|
||||
* 目前可正确获取圣遗物名称了,`#圣遗物列表`如有错误重新获角色信息后即正常
|
||||
* 雷神、莫娜的元素伤害字段数据错误fix
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
|
||||
* `#更新全部面板` 功能暂时恢复
|
||||
* 目前可直接使用,无需token
|
||||
* 部分网络可能无法请求,等待后续服务更新
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
|
||||
* 服务来自enka.shinshin.moe,部分网络可能无法请求,请使用科学处理
|
||||
|
||||
# 1.6.1 ~ 1.6.3
|
||||
# 1.6.1 ~ 1.6.4
|
||||
|
||||
* 增加`#喵喵面板设置`命令,可更精细的设置是否允许好友/临时对话/群使用面板功能
|
||||
* 增加`#录入夜兰面板` 命令,可在更新服务不可用时手工录入角色面板信息
|
||||
|
@ -493,9 +493,7 @@ export async function getProfile(e, mode = "refresh") {
|
||||
return true;
|
||||
}
|
||||
let leftMsg = "";
|
||||
if (!lodash.isUndefined(data.leftCount)) {
|
||||
leftMsg = `今日剩余${data.leftCount}次请求机会。`
|
||||
}
|
||||
|
||||
if (!data.chars) {
|
||||
e.reply("获取角色面板数据失败,请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~");
|
||||
} else {
|
||||
@ -832,6 +830,9 @@ export async function getArtis(e, { render }) {
|
||||
/* 处理圣遗物 */
|
||||
if (ds.artis) {
|
||||
lodash.forEach(ds.artis, (arti) => {
|
||||
if (!arti.name) {
|
||||
return;
|
||||
}
|
||||
let mark = Reliquaries.getMark(name, arti.attrs);
|
||||
let maxMark = Reliquaries.getMaxMark(name, arti.main[0] || "");
|
||||
arti.mark = Format.comma(mark, 1);
|
||||
@ -846,7 +847,6 @@ export async function getArtis(e, { render }) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (artis.length === 0) {
|
||||
e.reply("请先获取角色面板数据后再查看圣遗物列表...");
|
||||
await profileHelp(e);
|
||||
|
@ -5,19 +5,18 @@ import Format from "./Format.js";
|
||||
import Character from "./models/Character.js";
|
||||
import Reliquaries from "./models/Reliquaries.js";
|
||||
|
||||
import Data from "./data/enka.js";
|
||||
|
||||
const _path = process.cwd();
|
||||
const cfgPath = `${_path}/plugins/miao-plugin/config.js`;
|
||||
let config = {};
|
||||
//try {
|
||||
|
||||
if (fs.existsSync(cfgPath)) {
|
||||
let fileData = await import (`file://${cfgPath}`);
|
||||
if (fileData && fileData.config) {
|
||||
config = fileData.config;
|
||||
}
|
||||
}
|
||||
//} catch (e) {
|
||||
// do nth
|
||||
//}
|
||||
|
||||
const userPath = `${_path}/data/UserData/`;
|
||||
|
||||
@ -25,368 +24,11 @@ if (!fs.existsSync(userPath)) {
|
||||
fs.mkdirSync(userPath);
|
||||
}
|
||||
|
||||
const artifactMap = {
|
||||
'生命值': {
|
||||
title: "小生命"
|
||||
},
|
||||
'生命值_百分比': {
|
||||
title: "大生命",
|
||||
pct: true
|
||||
},
|
||||
'暴击率': {
|
||||
title: "暴击率",
|
||||
pct: true
|
||||
},
|
||||
'暴击伤害': {
|
||||
title: "暴击伤害",
|
||||
pct: true
|
||||
},
|
||||
'防御力': {
|
||||
title: "小防御"
|
||||
},
|
||||
'防御力_百分比': {
|
||||
title: "大防御",
|
||||
pct: true
|
||||
},
|
||||
'攻击力': {
|
||||
title: "小攻击"
|
||||
},
|
||||
'攻击力_百分比': {
|
||||
title: "大攻击",
|
||||
pct: true
|
||||
},
|
||||
'元素精通': {
|
||||
title: "元素精通"
|
||||
},
|
||||
'元素充能效率': {
|
||||
title: "充能效率",
|
||||
pct: true
|
||||
},
|
||||
'治疗加成': {
|
||||
title: "治疗加成",
|
||||
pct: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let posIdx = {
|
||||
"生之花": {
|
||||
idx: 1
|
||||
},
|
||||
"死之羽": {
|
||||
idx: 2
|
||||
},
|
||||
"时之沙": {
|
||||
idx: 3
|
||||
},
|
||||
"空之杯": {
|
||||
idx: 4
|
||||
},
|
||||
"理之冠": {
|
||||
idx: 5
|
||||
}
|
||||
};
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
let Data = {
|
||||
getData(uid, data) {
|
||||
let ret = {
|
||||
uid,
|
||||
chars: {}
|
||||
};
|
||||
|
||||
lodash.forEach({
|
||||
name: "角色名称",
|
||||
avatar: "头像ID",
|
||||
lv: "冒险等阶"
|
||||
}, (title, key) => {
|
||||
ret[key] = data[title] || "";
|
||||
})
|
||||
|
||||
lodash.forEach(data.items, (ds) => {
|
||||
let char = Data.getAvatar(ds);
|
||||
ret.chars[char.id] = char;
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
getAvatar(data) {
|
||||
let char = Character.get(data["英雄Id"]);
|
||||
return {
|
||||
id: data["英雄Id"],
|
||||
name: char ? char.name : "",
|
||||
lv: data['等级'],
|
||||
attr: Data.getAttr(data),
|
||||
// weapon: Data.getWeapon(data),
|
||||
artis: Data.getArtifact(data),
|
||||
//cons: data["命之座数量"] * 1 || 0,
|
||||
//talent: Data.getTalent(data)
|
||||
};
|
||||
},
|
||||
getAttr(data) {
|
||||
let ret = {};
|
||||
let attrKey = {
|
||||
atk: "攻击力_总",
|
||||
atkBase: "属性攻击力",
|
||||
def: "防御力_总",
|
||||
defBase: "属性防御力",
|
||||
hp: "生命值上限_总",
|
||||
hpBase: "属性生命值上限",
|
||||
mastery: "属性元素精通",
|
||||
cRate: {
|
||||
title: "属性暴击率",
|
||||
pct: true
|
||||
},
|
||||
cDmg: {
|
||||
title: "属性暴击伤害",
|
||||
pct: true
|
||||
},
|
||||
hInc: {
|
||||
title: "属性治疗加成",
|
||||
pct: true
|
||||
},
|
||||
recharge: {
|
||||
title: "属性元素充能效率",
|
||||
pct: true
|
||||
}
|
||||
};
|
||||
lodash.forEach(attrKey, (cfg, key) => {
|
||||
if (typeof (cfg) === "string") {
|
||||
cfg = {title: cfg};
|
||||
}
|
||||
let val = data[cfg.title] || "";
|
||||
if (cfg.pct) {
|
||||
val = (val * 100).toFixed(2)
|
||||
}
|
||||
ret[key] = val;
|
||||
});
|
||||
let maxDmg = 0;
|
||||
lodash.forEach("火水草雷风冰岩".split(""), (key) => {
|
||||
maxDmg = Math.max(data[`属性${key}元素伤害加成`] * 1, maxDmg);
|
||||
});
|
||||
ret.dmgBonus = (maxDmg * 100).toFixed(2);
|
||||
ret.phyBonus = (data[`属性物理伤害加成`] * 100).toFixed(2);
|
||||
|
||||
return ret;
|
||||
},
|
||||
getWeapon(data) {
|
||||
return {
|
||||
name: data['武器名称'],
|
||||
lv: data['武器等级'],
|
||||
refine: data["武器精炼"]
|
||||
}
|
||||
},
|
||||
getArtifact(data) {
|
||||
let ret = {};
|
||||
let get = function (idx, key) {
|
||||
let v = data[`圣遗物${idx}${key}`];
|
||||
let ret = /^([^\d]*)([\d\.\-]*)$/.exec(v);
|
||||
if (ret && ret[1]) {
|
||||
let title = ret[1], val = ret[2];
|
||||
if (artifactMap[title]) {
|
||||
if (artifactMap[title].pct) {
|
||||
val = (val * 100).toFixed(2);
|
||||
}
|
||||
title = artifactMap[title].title;
|
||||
}
|
||||
return [title, val];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
for (let idx = 1; idx <= 5; idx++) {
|
||||
ret[`arti${idx}`] = {
|
||||
name: data[`圣遗物${idx}名称`],
|
||||
type: data[`圣遗物${idx}类型`],
|
||||
main: get(idx, "主词条"),
|
||||
attrs: [
|
||||
get(idx, "副词条1"),
|
||||
get(idx, "副词条2"),
|
||||
get(idx, "副词条3"),
|
||||
get(idx, "副词条4"),
|
||||
]
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getTalent(data) {
|
||||
let ret = {};
|
||||
lodash.forEach({
|
||||
a: 1,
|
||||
e: 2,
|
||||
q: 3
|
||||
}, (idx, key) => {
|
||||
let val = data[`天赋主动名称${idx}`]
|
||||
let regRet = /等级(\d*)$/.exec(val);
|
||||
if (regRet && regRet[1]) {
|
||||
ret[key] = regRet[1] * 1 || 1
|
||||
} else {
|
||||
ret[key] = 1;
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
let Data2 = {
|
||||
getData(uid, data) {
|
||||
|
||||
let ret = {
|
||||
uid,
|
||||
chars: {}
|
||||
}
|
||||
|
||||
lodash.forEach({
|
||||
name: "nickname",
|
||||
avatar: "profilePicture.avatarId",
|
||||
lv: "level"
|
||||
}, (src, key) => {
|
||||
ret[key] = lodash.get(data.playerInfo, src, "");
|
||||
})
|
||||
|
||||
lodash.forEach(data.avatarInfoList, (ds) => {
|
||||
let char = Data2.getAvatar(ds);
|
||||
ret.chars[char.id] = char;
|
||||
})
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
getAvatar(data) {
|
||||
let char = Character.get(data.avatarId);
|
||||
return {
|
||||
id: data["avatarId"],
|
||||
name: char ? char.name : "",
|
||||
dataSource: "shin",
|
||||
lv: data.propMap['4001'].val * 1,
|
||||
attr: Data2.getAttr(data.fightPropMap),
|
||||
// weapon: Data.getWeapon(data),
|
||||
artis: Data2.getArtifact(data.equipList),
|
||||
//cons: data["命之座数量"] * 1 || 0,
|
||||
//talent: Data.getTalent(data)
|
||||
};
|
||||
},
|
||||
getAttr(data) {
|
||||
let ret = {};
|
||||
let attrKey = {
|
||||
// atk: 2001,
|
||||
atkBase: 4,
|
||||
def: 2002,
|
||||
defBase: 7,
|
||||
hp: 2000,
|
||||
hpBase: 1,
|
||||
mastery: 28,
|
||||
cRate: {
|
||||
src: 20,
|
||||
pct: true
|
||||
},
|
||||
cDmg: {
|
||||
src: 22,
|
||||
pct: true
|
||||
},
|
||||
hInc: {
|
||||
src: 26,
|
||||
pct: true
|
||||
},
|
||||
recharge: {
|
||||
src: 23,
|
||||
pct: true
|
||||
}
|
||||
};
|
||||
lodash.forEach(attrKey, (cfg, key) => {
|
||||
if (!lodash.isObject(cfg)) {
|
||||
cfg = {src: cfg};
|
||||
}
|
||||
let val = data[cfg.src] || 0;
|
||||
if (cfg.pct) {
|
||||
val = val * 100
|
||||
}
|
||||
ret[key] = val;
|
||||
});
|
||||
ret.atk = data['4'] * (1 + data['6']) + data['5'];
|
||||
let maxDmg = 0;
|
||||
// 火40 水42 风44 岩45 冰46 雷46
|
||||
// 41 雷
|
||||
lodash.forEach("40,41,42,43,44,45,45,46".split(","), (key) => {
|
||||
maxDmg = Math.max(data[key] * 1, maxDmg);
|
||||
});
|
||||
// phy 30
|
||||
ret.dmgBonus = maxDmg * 100;
|
||||
ret.phyBonus = data['30'] * 100;
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
getArtifact(data) {
|
||||
let ret = {};
|
||||
|
||||
let artiIdx = {
|
||||
EQUIP_BRACER: 1,
|
||||
EQUIP_NECKLACE: 2,
|
||||
EQUIP_SHOES: 3,
|
||||
EQUIP_RING: 4,
|
||||
EQUIP_DRESS: 5
|
||||
}
|
||||
let attrMap = {
|
||||
HP: "小生命",
|
||||
HP_PERCENT: "大生命",
|
||||
ATTACK: "小攻击",
|
||||
ATTACK_PERCENT: "大攻击",
|
||||
DEFENSE: "小防御",
|
||||
DEFENSE_PERCENT: "大防御",
|
||||
FIRE_ADD_HURT: "火元素伤害加成",
|
||||
ICE_ADD_HURT: "冰元素伤害加成",
|
||||
ROCK_ADD_HURT: "岩元素伤害加成",
|
||||
ELEC_ADD_HURT: "雷元素伤害加成",
|
||||
WIND_ADD_HURT: "风元素伤害加成",
|
||||
WATER_ADD_HURT: "水元素伤害加成",
|
||||
PHYSICAL_ADD_HURT: "物理伤害加成",
|
||||
HEAL_ADD: "治疗加成",
|
||||
ELEMENT_MASTERY: "元素精通",
|
||||
CRITICAL: "暴击率",
|
||||
CRITICAL_HURT: "暴击伤害",
|
||||
CHARGE_EFFICIENCY: "充能效率",
|
||||
}
|
||||
|
||||
let get = function (d) {
|
||||
if (!d) {
|
||||
return [];
|
||||
}
|
||||
let id = d.appendPropId || d.mainPropId || "";
|
||||
id = id.replace("FIGHT_PROP_", "");
|
||||
if (!attrMap[id]) {
|
||||
return [];
|
||||
}
|
||||
return [attrMap[id], d.statValue];
|
||||
|
||||
}
|
||||
lodash.forEach(data, (ds) => {
|
||||
let flat = ds.flat || {}, sub = flat.reliquarySubstats || [];
|
||||
let idx = artiIdx[flat.equipType];
|
||||
if (!idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret[`arti${idx}`] = {
|
||||
name: "",
|
||||
id: ds.itemId,
|
||||
main: get(flat.reliquaryMainstat),
|
||||
attrs: [
|
||||
get(sub[0]),
|
||||
get(sub[1]),
|
||||
get(sub[2]),
|
||||
get(sub[3])
|
||||
]
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
},
|
||||
};
|
||||
|
||||
let Profile = {
|
||||
async request(uid, e) {
|
||||
let api = `https://enka.shinshin.moe/u/${uid}/__data.json`;
|
||||
@ -395,7 +37,7 @@ let Profile = {
|
||||
e.reply("请求过快,请稍后重试..");
|
||||
return false;
|
||||
} else if (inCd === 'pending') {
|
||||
e.reply("距上次请求刷新成功间隔小于2分钟,请稍后重试..");
|
||||
e.reply("距上次请求刷新成功间隔小于5分钟,请稍后重试..");
|
||||
return false;
|
||||
}
|
||||
await redis.set(`miao:role-all:${uid}`, 'loading', {EX: 20});
|
||||
@ -414,78 +56,29 @@ let Profile = {
|
||||
e.reply(`请打开角色展柜的显示详情`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// enka服务测冷却时间5分钟
|
||||
await redis.set(`miao:role-all:${uid}`, 'pending', {EX: 300});
|
||||
let userData = {};
|
||||
userData = Profile.save(uid, data, 'enka')
|
||||
return userData;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
e.reply(`请求失败`);
|
||||
return false;
|
||||
}
|
||||
// 请求成功Bot侧对该uid冷却10分钟
|
||||
// 请勿将时间改短,10分钟之内若发起请求会命中服务侧的uid缓存,返回之前的数据,并导致服务侧重新计时
|
||||
await redis.set(`miao:role-all:${uid}`, 'pending', {EX: 120});
|
||||
|
||||
let userData = {};
|
||||
userData = Profile.save(uid, data, true)
|
||||
|
||||
userData.leftCount = 99;
|
||||
return userData;
|
||||
|
||||
},
|
||||
async request_bak(uid, e) {
|
||||
let cfg = config.miaoApi || {};
|
||||
if (!cfg.api) {
|
||||
e.reply("该功能为小范围非公开功能,需具备Token才可使用~");
|
||||
return false;
|
||||
}
|
||||
if (!cfg.qq || !cfg.token || cfg.token.length !== 32) {
|
||||
e.reply("Token错误,无法请求数据~");
|
||||
return false;
|
||||
}
|
||||
let inCd = await redis.get(`miao:role-all:${uid}`);
|
||||
if (inCd === 'loading') {
|
||||
e.reply("请求过快,请稍后重试..");
|
||||
return false;
|
||||
} else if (inCd === 'pending') {
|
||||
e.reply("距上次请求刷新成功间隔小于10分钟,请稍后重试..");
|
||||
return false;
|
||||
}
|
||||
await redis.set(`miao:role-all:${uid}`, 'loading', {EX: 20});
|
||||
e.reply("开始获取数据,可能会需要一定时间~");
|
||||
|
||||
await sleep(1000);
|
||||
|
||||
let api = `${cfg.api}?uid=${uid}&qq=${cfg.qq}&token=${cfg.token}`;
|
||||
if (e.avatar) {
|
||||
api += `&avatar=${e.avatar}`;
|
||||
}
|
||||
let req = await fetch(api);
|
||||
let data = await req.json();
|
||||
if (data.status !== 0 || !data.data) {
|
||||
e.reply(`请求失败:${data.msg || "未知错误"}`);
|
||||
return false;
|
||||
}
|
||||
// 请求成功Bot侧对该uid冷却10分钟
|
||||
// 请勿将时间改短,10分钟之内若发起请求会命中服务侧的uid缓存,返回之前的数据,并导致服务侧重新计时
|
||||
await redis.set(`miao:role-all:${uid}`, 'pending', {EX: 600});
|
||||
let leftCount = data.leftCount;
|
||||
data = data.data;
|
||||
let userData = {};
|
||||
if (data && data["角色名称"]) {
|
||||
userData = Profile.save(uid, data)
|
||||
}
|
||||
userData.leftCount = leftCount;
|
||||
return userData;
|
||||
},
|
||||
|
||||
save(uid, ds, isNewFormat = false) {
|
||||
save(uid, ds, dataSource = 'enka') {
|
||||
let userData = {};
|
||||
const userFile = `${userPath}/${uid}.json`;
|
||||
if (fs.existsSync(userFile)) {
|
||||
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
|
||||
}
|
||||
let data;
|
||||
if (isNewFormat) {
|
||||
data = Data2.getData(uid, ds);
|
||||
} else {
|
||||
|
||||
data = Data.getData(uid, ds);
|
||||
}
|
||||
|
||||
lodash.assignIn(userData, lodash.pick(data, "uid,name,lv,avatar".split(",")));
|
||||
userData.chars = userData.chars || {};
|
||||
|
242
components/data/enka.js
Normal file
242
components/data/enka.js
Normal file
@ -0,0 +1,242 @@
|
||||
import lodash from "lodash";
|
||||
import Character from "../models/Character.js";
|
||||
import meta from "./enka_meta.js";
|
||||
import cmeta from "./enka_char.js";
|
||||
import _Data from "../Data.js";
|
||||
|
||||
let _path = process.cwd();
|
||||
let relis = _Data.readJSON(`${_path}/plugins/miao-plugin/resources/meta/reliquaries/`, "data.json") || {};
|
||||
|
||||
let relisMap = {}
|
||||
|
||||
lodash.forEach(relis, (ds) => {
|
||||
relisMap[ds.name] = ds;
|
||||
})
|
||||
|
||||
|
||||
const artiIdx = {
|
||||
EQUIP_BRACER: 1,
|
||||
EQUIP_NECKLACE: 2,
|
||||
EQUIP_SHOES: 3,
|
||||
EQUIP_RING: 4,
|
||||
EQUIP_DRESS: 5
|
||||
};
|
||||
|
||||
const attrMap = {
|
||||
HP: "小生命",
|
||||
HP_PERCENT: "大生命",
|
||||
ATTACK: "小攻击",
|
||||
ATTACK_PERCENT: "大攻击",
|
||||
DEFENSE: "小防御",
|
||||
DEFENSE_PERCENT: "大防御",
|
||||
FIRE_ADD_HURT: "火元素伤害加成",
|
||||
ICE_ADD_HURT: "冰元素伤害加成",
|
||||
ROCK_ADD_HURT: "岩元素伤害加成",
|
||||
ELEC_ADD_HURT: "雷元素伤害加成",
|
||||
WIND_ADD_HURT: "风元素伤害加成",
|
||||
WATER_ADD_HURT: "水元素伤害加成",
|
||||
PHYSICAL_ADD_HURT: "物理伤害加成",
|
||||
HEAL_ADD: "治疗加成",
|
||||
ELEMENT_MASTERY: "元素精通",
|
||||
CRITICAL: "暴击率",
|
||||
CRITICAL_HURT: "暴击伤害",
|
||||
CHARGE_EFFICIENCY: "充能效率",
|
||||
};
|
||||
|
||||
let Data = {
|
||||
getData(uid, data) {
|
||||
let ret = {
|
||||
uid,
|
||||
chars: {}
|
||||
}
|
||||
|
||||
lodash.forEach({
|
||||
name: "nickname",
|
||||
avatar: "profilePicture.avatarId",
|
||||
lv: "level"
|
||||
}, (src, key) => {
|
||||
ret[key] = lodash.get(data.playerInfo, src, "");
|
||||
})
|
||||
|
||||
lodash.forEach(data.avatarInfoList, (ds) => {
|
||||
let char = Data.getAvatar(ds);
|
||||
ret.chars[char.id] = char;
|
||||
})
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
getAvatar(data) {
|
||||
let char = Character.get(data.avatarId);
|
||||
let ret = {
|
||||
id: data["avatarId"],
|
||||
name: char ? char.name : "",
|
||||
dataSource: "enka",
|
||||
lv: data.propMap['4001'].val * 1,
|
||||
fetter: data.fetterInfo.expLevel,
|
||||
attr: Data.getAttr(data.fightPropMap),
|
||||
weapon: Data.getWeapon(data.equipList),
|
||||
artis: Data.getArtifact(data.equipList),
|
||||
cons: data.talentIdList ? data.talentIdList.length : 0,
|
||||
talent: Data.getTalent(char.id, data.skillLevelMap, data.proudSkillExtraLevelMap || {})
|
||||
};
|
||||
return Data.dataFix(ret);
|
||||
},
|
||||
getAttr(data) {
|
||||
let ret = {};
|
||||
let attrKey = {
|
||||
// atk: 2001,
|
||||
atkBase: 4,
|
||||
def: 2002,
|
||||
defBase: 7,
|
||||
hp: 2000,
|
||||
hpBase: 1,
|
||||
mastery: 28,
|
||||
cRate: {
|
||||
src: 20,
|
||||
pct: true
|
||||
},
|
||||
cDmg: {
|
||||
src: 22,
|
||||
pct: true
|
||||
},
|
||||
hInc: {
|
||||
src: 26,
|
||||
pct: true
|
||||
},
|
||||
recharge: {
|
||||
src: 23,
|
||||
pct: true
|
||||
}
|
||||
};
|
||||
lodash.forEach(attrKey, (cfg, key) => {
|
||||
if (!lodash.isObject(cfg)) {
|
||||
cfg = {src: cfg};
|
||||
}
|
||||
let val = data[cfg.src] || 0;
|
||||
if (cfg.pct) {
|
||||
val = val * 100
|
||||
}
|
||||
ret[key] = val;
|
||||
});
|
||||
ret.atk = data['4'] * (1 + data['6']) + data['5'];
|
||||
let maxDmg = 0;
|
||||
// 火40 水42 风44 岩45 冰46 雷46
|
||||
// 41 雷
|
||||
lodash.forEach("40,41,42,43,44,45,45,46".split(","), (key) => {
|
||||
maxDmg = Math.max(data[key] * 1, maxDmg);
|
||||
});
|
||||
// phy 30
|
||||
ret.dmgBonus = maxDmg * 100;
|
||||
ret.phyBonus = data['30'] * 100;
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
getArtifact(data) {
|
||||
let ret = {};
|
||||
|
||||
let get = function (d) {
|
||||
if (!d) {
|
||||
return [];
|
||||
}
|
||||
let id = d.appendPropId || d.mainPropId || "";
|
||||
id = id.replace("FIGHT_PROP_", "");
|
||||
if (!attrMap[id]) {
|
||||
return [];
|
||||
}
|
||||
return [attrMap[id], d.statValue];
|
||||
|
||||
}
|
||||
lodash.forEach(data, (ds) => {
|
||||
let flat = ds.flat || {}, sub = flat.reliquarySubstats || [];
|
||||
let idx = artiIdx[flat.equipType];
|
||||
if (!idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
let setName = meta[flat.setNameTextMapHash] || "";
|
||||
let setCfg = relisMap[setName] || {name: "", sets: {}},
|
||||
artiCfg = setCfg.sets[`arti${idx}`] || {name: ""};
|
||||
|
||||
ret[`arti${idx}`] = {
|
||||
name: artiCfg.name,
|
||||
set: setCfg.name,
|
||||
level: Math.min(20, ((ds.reliquary && ds.reliquary.level) || 1) - 1),
|
||||
main: get(flat.reliquaryMainstat),
|
||||
attrs: [
|
||||
get(sub[0]),
|
||||
get(sub[1]),
|
||||
get(sub[2]),
|
||||
get(sub[3])
|
||||
]
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
},
|
||||
getWeapon(data) {
|
||||
let ds = {}
|
||||
lodash.forEach(data, (temp) => {
|
||||
if (temp.flat && temp.flat.itemType === "ITEM_WEAPON") {
|
||||
ds = temp;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
let {weapon, flat} = ds;
|
||||
return {
|
||||
name: meta[flat.nameTextMapHash],
|
||||
star: flat.rankLevel,
|
||||
leve: weapon.level,
|
||||
promote: weapon.promoteLevel,
|
||||
affix: lodash.values(weapon.affixMap)[0]
|
||||
}
|
||||
},
|
||||
getTalent(charid, ds = {}, ext = {}) {
|
||||
let cm = cmeta[charid] || {};
|
||||
let cn = cm.Skills || {}, ce = cm.ProudMap;
|
||||
let idx = 1;
|
||||
let idxMap = {1: 'a', 2: 'e', 3: 'q', 'a': 'a', 's': 'e', 'e': 'q'};
|
||||
lodash.forEach(cn, (n, id) => {
|
||||
let nRet = /skill_(\w)/.exec(n.toLowerCase());
|
||||
idxMap[id] = nRet && nRet[1] ? idxMap[nRet[1]] : idxMap[idx];
|
||||
idx++;
|
||||
});
|
||||
lodash.forEach(ce, (n, id) => {
|
||||
idxMap[n] = idxMap[id];
|
||||
})
|
||||
let ret = {};
|
||||
lodash.forEach(ds, (lv, id) => {
|
||||
let key = idxMap[id];
|
||||
ret[key] = {
|
||||
level_original: lv,
|
||||
level_current: lv
|
||||
}
|
||||
})
|
||||
lodash.forEach(ext, (lv, id) => {
|
||||
let key = idxMap[id];
|
||||
if (ret[key]) {
|
||||
ret[key].level_current = ret[key].level_current + lv;
|
||||
}
|
||||
})
|
||||
|
||||
return ret;
|
||||
},
|
||||
dataFix(ret) {
|
||||
|
||||
let {attr, id} = ret;
|
||||
id = id * 1;
|
||||
switch (id) {
|
||||
case 10000052:
|
||||
// 雷神被动加成fix
|
||||
attr.dmgBonus = Math.min(0, attr.dmgBonus - (attr.recharge - 100) * 0.4)
|
||||
break;
|
||||
case 10000041:
|
||||
// 莫娜被动fix
|
||||
attr.dmgBonus = Math.min(0, attr.dmgBonus - attr.recharge * 0.2)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
export default Data;
|
1098
components/data/enka_char.js
Normal file
1098
components/data/enka_char.js
Normal file
File diff suppressed because it is too large
Load Diff
387
components/data/enka_meta.js
Normal file
387
components/data/enka_meta.js
Normal file
@ -0,0 +1,387 @@
|
||||
export default {
|
||||
20848859: "黑岩斩刀",
|
||||
33330467: "元素熟练",
|
||||
37147251: "匣里日月",
|
||||
43015699: "待定",
|
||||
54857595: "止水息雷",
|
||||
83115355: "被怜爱的少女",
|
||||
85795635: "专注",
|
||||
88505754: "枫原万叶",
|
||||
135182203: "止水息雷",
|
||||
147298547: "流浪大地的乐团",
|
||||
156294403: "沉沦之心",
|
||||
160493219: "暗铁剑",
|
||||
168956722: "七七",
|
||||
197755235: "贯虹之槊",
|
||||
212557731: "祭雷之人",
|
||||
240385755: "破浪",
|
||||
246984427: "踏火息雷",
|
||||
262428003: "祭冰之人",
|
||||
270124867: "护国的无垢之心",
|
||||
287454963: "祭风之人",
|
||||
288666635: "无垢之心",
|
||||
302691299: "琥珀玥",
|
||||
303155515: "离簇不归",
|
||||
310247243: "神乐之真意",
|
||||
334242634: "申鹤",
|
||||
339931171: "乘胜追击",
|
||||
342097547: "辰砂之纺锤",
|
||||
346510395: "衔珠海皇",
|
||||
368014203: "斩裂晴空的龙脊",
|
||||
391273955: "斫断黑翼的利齿",
|
||||
411685275: "钢轮弓",
|
||||
479076483: "冷刃",
|
||||
481755219: "黑岩刺枪",
|
||||
486287579: "余热",
|
||||
500612819: "「旗杆」",
|
||||
500987603: "(test)穿模测试",
|
||||
506630267: "顺风而行",
|
||||
514784907: "踏火止水",
|
||||
521221323: "护国的无垢之心",
|
||||
540938627: "掠食者",
|
||||
566772267: "御伽大王御伽话",
|
||||
577103787: "能量沐浴",
|
||||
578575283: "流月针",
|
||||
597991835: "白夜皓月",
|
||||
613846163: "降世",
|
||||
618786571: "钺矛",
|
||||
623494555: "摧坚",
|
||||
623534363: "西风秘典",
|
||||
630452219: "樱之斋宫",
|
||||
646100491: "千岩诀·同心",
|
||||
650049651: "风花之颂",
|
||||
655825874: "云堇",
|
||||
656120259: "神射手之誓",
|
||||
680510411: "白影剑",
|
||||
688991243: "息灾",
|
||||
693354267: "尘世之锁",
|
||||
697277554: "烟绯",
|
||||
716252627: "千岩长枪",
|
||||
729851187: "冰之川与雪之砂",
|
||||
735056795: "西风大剑",
|
||||
807607555: "天空之卷",
|
||||
824949859: "嘟嘟!大冒险",
|
||||
828711395: "阿莫斯之弓",
|
||||
836208539: "炊金",
|
||||
850802171: "白铁大剑",
|
||||
855894507: "战狂",
|
||||
862591315: "苍白之火",
|
||||
877751435: "宗室大剑",
|
||||
902264035: "风鹰剑",
|
||||
902282051: "收割",
|
||||
909145139: "护国的无垢之心",
|
||||
930640955: "钟剑",
|
||||
933076627: "冰风迷途的勇士",
|
||||
942758755: "专注",
|
||||
944332883: "斫峰之刃",
|
||||
949506483: "海洋的胜利",
|
||||
968378595: "西风之鹰的抗争",
|
||||
968893378: "班尼特",
|
||||
991968139: "非时之梦·常世灶食",
|
||||
1006042610: "神里绫华",
|
||||
1021898539: "弹弓",
|
||||
1021947690: "魈",
|
||||
1028735635: "抗争的践行之歌",
|
||||
1053433018: "砂糖",
|
||||
1072884907: "万国诸海图谱",
|
||||
1075647299: "松籁响起之时",
|
||||
1082448331: "微光的海渊民",
|
||||
1089950259: "天空之傲",
|
||||
1097898243: "沉重",
|
||||
1103732675: "幸运儿",
|
||||
1113306282: "莫娜",
|
||||
1114777131: "和弦",
|
||||
1119368259: "旅程",
|
||||
1130996346: "香菱",
|
||||
1133599347: "矢志不忘",
|
||||
1148024603: "「渔获」",
|
||||
1154009435: "试作星镰",
|
||||
1163263227: "流浪乐章",
|
||||
1163616891: "霜葬",
|
||||
1182966603: "佣兵重剑",
|
||||
1186209435: "赌徒",
|
||||
1212345779: "角斗士的终幕礼",
|
||||
1217552947: "白刃流转",
|
||||
1240067179: "西风猎弓",
|
||||
1319974859: "激励",
|
||||
1321135667: "匣里龙吟",
|
||||
1337666507: "千岩牢固",
|
||||
1344953075: "顺风而行",
|
||||
1345343763: "磐岩结绿",
|
||||
1383639611: "奇迹",
|
||||
1388004931: "飞天御剑",
|
||||
1390797107: "白缨枪",
|
||||
1404688115: "别离的思念之歌",
|
||||
1406746947: "异世界行记",
|
||||
1414366819: "金璋皇极",
|
||||
1437658243: "螭骨剑",
|
||||
1438974835: "逆飞的流星",
|
||||
1455107995: "四风原典",
|
||||
1468367538: "迪奥娜",
|
||||
1479961579: "铁影阔剑",
|
||||
1483922610: "九条裟罗",
|
||||
1485303435: "注能之刺",
|
||||
1492752155: "气定神闲",
|
||||
1499235563: "乘胜追击",
|
||||
1499817443: "苍翠之风",
|
||||
1516554699: "石英大剑",
|
||||
1522029867: "踏火息雷",
|
||||
1524173875: "炽烈的炎之魔女",
|
||||
1533656818: "旅行者",
|
||||
1541919827: "染血的骑士道",
|
||||
1545992315: "「正义」",
|
||||
1558036915: "辰砂往生录",
|
||||
1562601179: "翠绿之影",
|
||||
1588620330: "神里绫人",
|
||||
1595734083: "(test)穿模测试",
|
||||
1600275315: "波乱月白经津",
|
||||
1608953539: "黎明神剑",
|
||||
1610242915: "传承",
|
||||
1628928163: "风花之愿",
|
||||
1632377563: "渡过烈火的贤人",
|
||||
1651985379: "极昼的先兆者",
|
||||
1660598451: "岩藏之胤",
|
||||
1675686363: "祭礼大剑",
|
||||
1706534267: "有话直说",
|
||||
1722706579: "止水融冰",
|
||||
1745286795: "名士振舞",
|
||||
1745712907: "驭浪的海祇民",
|
||||
1751039235: "昔日宗室之仪",
|
||||
1756609915: "海染砗磲",
|
||||
1771603299: "金璋皇极",
|
||||
1773425155: "降临之剑",
|
||||
1789612403: "回响",
|
||||
1820235315: "无矢之歌",
|
||||
1836628747: "叛逆的守护者",
|
||||
1860795787: "曚云之月",
|
||||
1864015138: "刻晴",
|
||||
1873342283: "平息鸣雷的尊者",
|
||||
1890163363: "不灭月华",
|
||||
1901973075: "冬极白星",
|
||||
1921418842: "诺艾尔",
|
||||
1932742643: "灭却之戒法",
|
||||
1934830979: "无尽的渴慕",
|
||||
1940821986: "久岐忍",
|
||||
1940919994: "胡桃",
|
||||
1966438658: "安柏",
|
||||
1982136171: "专注",
|
||||
1990641987: "祭礼剑",
|
||||
1990820123: "天目影打刀",
|
||||
1991707099: "试作斩岩",
|
||||
1997709467: "和璞鸢",
|
||||
2006422931: "千岩古剑",
|
||||
2009975571: "(test)穿模测试",
|
||||
2017033267: "气定神闲",
|
||||
2025598051: "顺风而行",
|
||||
2040573235: "悠古的磐岩",
|
||||
2060049099: "祭火之人",
|
||||
2108574027: "碎石",
|
||||
2109571443: "专注",
|
||||
2125206395: "银剑",
|
||||
2149411851: "金璋皇极",
|
||||
2172529947: "乘胜追击",
|
||||
2176134843: "专注",
|
||||
2190368347: "决",
|
||||
2191797987: "冒险家",
|
||||
2195665683: "祭礼残章",
|
||||
2242027395: "黑檀弓",
|
||||
2276480763: "绝缘之旗印",
|
||||
2279290283: "魔导绪论",
|
||||
2297485451: "速射弓斗",
|
||||
2312640651: "气定神闲",
|
||||
2317820211: "注能之针",
|
||||
2322648115: "粉碎",
|
||||
2324146259: "白辰之环",
|
||||
2340970067: "历练的猎弓",
|
||||
2359799475: "恶王丸",
|
||||
2364208851: "行者之心",
|
||||
2365025043: "街巷游侠",
|
||||
2375993851: "宗室长剑",
|
||||
2383998915: "驭浪的海祇民",
|
||||
2384519283: "弹弓",
|
||||
2388785242: "早柚",
|
||||
2400012995: "祭礼弓",
|
||||
2410593283: "无锋剑",
|
||||
2417717595: "暗巷猎手",
|
||||
2425414923: "落霞",
|
||||
2433755451: "揭旗的叛逆之歌",
|
||||
2440850563: "回响长天的诗歌",
|
||||
2466140362: "温迪",
|
||||
2469300579: "乘胜追击",
|
||||
2470306939: "飞雷御执",
|
||||
2474354867: "西风剑",
|
||||
2476346187: "踏火止水",
|
||||
2491797315: "喜多院十文字",
|
||||
2504399314: "宵宫",
|
||||
2512309395: "如雷的盛怒",
|
||||
2521338131: "试作金珀",
|
||||
2534304035: "雾切御腰物",
|
||||
2539208459: "证誓之明瞳",
|
||||
2546254811: "华馆梦醒形骸记",
|
||||
2556914683: "绝弦",
|
||||
2587614459: "忍冬之果",
|
||||
2614170427: "飞天大御剑",
|
||||
2646367730: "北斗",
|
||||
2664629131: "匣里灭辰",
|
||||
2666951267: "训练大剑",
|
||||
2673337443: "注能之矢",
|
||||
2679781122: "甘雨",
|
||||
2684365579: "登场乐",
|
||||
2705029563: "口袋魔导书",
|
||||
2713453234: "八重神子",
|
||||
2719832059: "(test)穿模测试",
|
||||
2743659331: "激流",
|
||||
2749508387: "金璋皇极",
|
||||
2749853923: "腐殖之剑",
|
||||
2753539619: "雪葬的星银",
|
||||
2764598579: "流放者",
|
||||
2792766467: "无工之剑",
|
||||
2796697027: "新手长枪",
|
||||
2832648187: "宗室长弓",
|
||||
2834803571: "金璋皇极",
|
||||
2848374378: "夜兰",
|
||||
2853296811: "穿刺高天的利齿",
|
||||
2871793795: "锐利",
|
||||
2876340530: "重云",
|
||||
2890909531: "武人",
|
||||
2893964243: "飞矢传书",
|
||||
2915865819: "渊中霞彩",
|
||||
2918525947: "飞雷之弦振",
|
||||
2935286715: "宗室猎枪",
|
||||
2947140987: "暗巷闪光",
|
||||
2949448555: "苍古自由之誓",
|
||||
2963220587: "翡玉法球",
|
||||
3001782875: "气定神闲",
|
||||
3018479371: "船歌",
|
||||
3024507506: "雷电将军",
|
||||
3063488107: "强力攻击",
|
||||
3068316954: "荒泷一斗",
|
||||
3070169307: "铁尖枪",
|
||||
3079462611: "驭浪的海祇民",
|
||||
3090373787: "暗巷的酒与诗",
|
||||
3097441915: "以理服人",
|
||||
3112448011: "决心",
|
||||
3112679155: "终末嗟叹之诗",
|
||||
3156385731: "昭心",
|
||||
3169209451: "弓藏",
|
||||
3192689683: "霜葬",
|
||||
3221566250: "琴",
|
||||
3235324891: "护摩之杖",
|
||||
3252085691: "顺风而行",
|
||||
3258658763: "嗜魔",
|
||||
3265161211: "注能之锋",
|
||||
3273999011: "黑岩绯玉",
|
||||
3277782506: "菲谢尔",
|
||||
3302787771: "霜葬",
|
||||
3305772819: "奔袭战术",
|
||||
3314157803: "克柔",
|
||||
3337185491: "浅濑之弭",
|
||||
3337249451: "过载",
|
||||
3339083250: "可莉",
|
||||
3344622722: "丽莎",
|
||||
3364338659: "无边际的眷顾",
|
||||
3371922315: "神樱神游神乐舞",
|
||||
3378007475: "黑岩长剑",
|
||||
3400133546: "五郎",
|
||||
3406113971: "顺风而行",
|
||||
3421967235: "吃虎鱼刀",
|
||||
3439749859: "苍翠猎弓",
|
||||
3443142923: "龙脊长枪",
|
||||
3447737235: "黑岩战弓",
|
||||
3456986819: "嘟嘟可故事集",
|
||||
3465493459: "精准",
|
||||
3500935003: "讨龙英杰谭",
|
||||
3535784755: "勇士之心",
|
||||
3541083923: "角斗士",
|
||||
3555115602: "托马",
|
||||
3584825427: "学徒笔记",
|
||||
3587062891: "千岩诀·同心",
|
||||
3587621259: "笛剑",
|
||||
3600623979: "猎弓",
|
||||
3608180322: "迪卢克",
|
||||
3618167299: "学士",
|
||||
3625393819: "试作澹月",
|
||||
3626268211: "来歆余响",
|
||||
3673792067: "旅行剑",
|
||||
3684723963: "雨裁",
|
||||
3689108098: "埃洛伊",
|
||||
3717667418: "优菈",
|
||||
3717849275: "薙草之稻光",
|
||||
3719372715: "甲级宝珏",
|
||||
3722933411: "试作古华",
|
||||
3755004051: "西风长枪",
|
||||
3762437019: "(test)穿模测试",
|
||||
3775299170: "芭芭拉",
|
||||
3782508715: "游医",
|
||||
3796702635: "变化万端",
|
||||
3796905611: "黑剑",
|
||||
3816664530: "旅行者",
|
||||
3827789435: "宗室秘法录",
|
||||
3832443723: "不屈",
|
||||
3836188467: "无羁的朱赤之蝶",
|
||||
3847143266: "达达利亚",
|
||||
3862787418: "钟离",
|
||||
3890292467: "教官",
|
||||
3898539027: "浮游四方的灵云",
|
||||
3914045794: "珊瑚宫心海",
|
||||
3914951691: "赤角石溃杵",
|
||||
3933622347: "天空之翼",
|
||||
3949653579: "幽夜华尔兹",
|
||||
3966753539: "洗濯诸类之形",
|
||||
3975746731: "鸦羽弓",
|
||||
3995710363: "狼的末路",
|
||||
3996017211: "收割",
|
||||
3999792907: "祭水之人",
|
||||
4000770243: "街巷伏击",
|
||||
4022012131: "乘胜追击",
|
||||
4049410651: "决斗之枪",
|
||||
4055003299: "天空之刃",
|
||||
4060235987: "日月辉",
|
||||
4080317355: "勇气",
|
||||
4082302819: "守护之心",
|
||||
4090429643: "沐浴龙血的剑",
|
||||
4103022435: "铁蜂刺",
|
||||
4103766499: "黑缨枪",
|
||||
4108620722: "阿贝多",
|
||||
4113638323: "昭理的鸢之枪",
|
||||
4119663210: "凯亚",
|
||||
4122509083: "断浪长鳍",
|
||||
4124851547: "雾切之回光",
|
||||
4127888970: "凝光",
|
||||
4137694339: "(test)竿测试",
|
||||
4139294531: "信使",
|
||||
4144069251: "追忆之注连",
|
||||
4158505619: "天空之脊",
|
||||
4160147242: "雷泽",
|
||||
4162981171: "(test)穿模测试",
|
||||
4186179883: "破魔之弓",
|
||||
4193089947: "桂木斩长正",
|
||||
4197635682: "行秋",
|
||||
4226083179: "名士振舞",
|
||||
4230231107: "若水",
|
||||
4245213187: "注能之卷",
|
||||
4258047555: "极夜二重奏",
|
||||
4260733330: "罗莎莉亚",
|
||||
4267718859: "反曲弓",
|
||||
4273845410: "辛焱",
|
||||
4275754179: "如狼般狩猎者",
|
||||
FIGHT_PROP_ATTACK: "攻击力",
|
||||
FIGHT_PROP_CHARGE_EFFICIENCY: "元素充能效率",
|
||||
FIGHT_PROP_CRITICAL: "暴击率",
|
||||
FIGHT_PROP_CRITICAL_HURT: "暴击伤害",
|
||||
FIGHT_PROP_DEFENSE: "防御力",
|
||||
FIGHT_PROP_ELEC_ADD_HURT: "雷元素伤害加成",
|
||||
FIGHT_PROP_ELEMENT_MASTERY: "元素精通",
|
||||
FIGHT_PROP_FIRE_ADD_HURT: "火元素伤害加成",
|
||||
FIGHT_PROP_GRASS_ADD_HURT: "草元素伤害加成",
|
||||
FIGHT_PROP_HEALED_ADD: "受治疗加成",
|
||||
FIGHT_PROP_HEAL_ADD: "治疗加成",
|
||||
FIGHT_PROP_ICE_ADD_HURT: "冰元素伤害加成",
|
||||
FIGHT_PROP_MAX_HP: "生命值上限",
|
||||
FIGHT_PROP_PHYSICAL_ADD_HURT: "物理伤害加成",
|
||||
FIGHT_PROP_ROCK_ADD_HURT: "岩元素伤害加成",
|
||||
FIGHT_PROP_SHIELD_COST_MINUS_RATIO: "护盾强效",
|
||||
FIGHT_PROP_WATER_ADD_HURT: "水元素伤害加成",
|
||||
FIGHT_PROP_WIND_ADD_HURT: "风元素伤害加成",
|
||||
level: "等级",
|
||||
}
|
205
components/data/miao.js
Normal file
205
components/data/miao.js
Normal file
@ -0,0 +1,205 @@
|
||||
import lodash from "lodash";
|
||||
import Character from "../models/Character.js";
|
||||
|
||||
const artifactMap = {
|
||||
'生命值': {
|
||||
title: "小生命"
|
||||
},
|
||||
'生命值_百分比': {
|
||||
title: "大生命",
|
||||
pct: true
|
||||
},
|
||||
'暴击率': {
|
||||
title: "暴击率",
|
||||
pct: true
|
||||
},
|
||||
'暴击伤害': {
|
||||
title: "暴击伤害",
|
||||
pct: true
|
||||
},
|
||||
'防御力': {
|
||||
title: "小防御"
|
||||
},
|
||||
'防御力_百分比': {
|
||||
title: "大防御",
|
||||
pct: true
|
||||
},
|
||||
'攻击力': {
|
||||
title: "小攻击"
|
||||
},
|
||||
'攻击力_百分比': {
|
||||
title: "大攻击",
|
||||
pct: true
|
||||
},
|
||||
'元素精通': {
|
||||
title: "元素精通"
|
||||
},
|
||||
'元素充能效率': {
|
||||
title: "充能效率",
|
||||
pct: true
|
||||
},
|
||||
'治疗加成': {
|
||||
title: "治疗加成",
|
||||
pct: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let posIdx = {
|
||||
"生之花": {
|
||||
idx: 1
|
||||
},
|
||||
"死之羽": {
|
||||
idx: 2
|
||||
},
|
||||
"时之沙": {
|
||||
idx: 3
|
||||
},
|
||||
"空之杯": {
|
||||
idx: 4
|
||||
},
|
||||
"理之冠": {
|
||||
idx: 5
|
||||
}
|
||||
};
|
||||
|
||||
let Data = {
|
||||
getData(uid, data) {
|
||||
let ret = {
|
||||
uid,
|
||||
chars: {}
|
||||
};
|
||||
|
||||
lodash.forEach({
|
||||
name: "角色名称",
|
||||
avatar: "头像ID",
|
||||
lv: "冒险等阶"
|
||||
}, (title, key) => {
|
||||
ret[key] = data[title] || "";
|
||||
})
|
||||
|
||||
lodash.forEach(data.items, (ds) => {
|
||||
let char = Data.getAvatar(ds);
|
||||
ret.chars[char.id] = char;
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
getAvatar(data) {
|
||||
let char = Character.get(data["英雄Id"]);
|
||||
return {
|
||||
id: data["英雄Id"],
|
||||
name: char ? char.name : "",
|
||||
lv: data['等级'],
|
||||
attr: Data.getAttr(data),
|
||||
// weapon: Data.getWeapon(data),
|
||||
artis: Data.getArtifact(data),
|
||||
//cons: data["命之座数量"] * 1 || 0,
|
||||
//talent: Data.getTalent(data)
|
||||
};
|
||||
},
|
||||
getAttr(data) {
|
||||
let ret = {};
|
||||
let attrKey = {
|
||||
atk: "攻击力_总",
|
||||
atkBase: "属性攻击力",
|
||||
def: "防御力_总",
|
||||
defBase: "属性防御力",
|
||||
hp: "生命值上限_总",
|
||||
hpBase: "属性生命值上限",
|
||||
mastery: "属性元素精通",
|
||||
cRate: {
|
||||
title: "属性暴击率",
|
||||
pct: true
|
||||
},
|
||||
cDmg: {
|
||||
title: "属性暴击伤害",
|
||||
pct: true
|
||||
},
|
||||
hInc: {
|
||||
title: "属性治疗加成",
|
||||
pct: true
|
||||
},
|
||||
recharge: {
|
||||
title: "属性元素充能效率",
|
||||
pct: true
|
||||
}
|
||||
};
|
||||
lodash.forEach(attrKey, (cfg, key) => {
|
||||
if (typeof (cfg) === "string") {
|
||||
cfg = {title: cfg};
|
||||
}
|
||||
let val = data[cfg.title] || "";
|
||||
if (cfg.pct) {
|
||||
val = (val * 100).toFixed(2)
|
||||
}
|
||||
ret[key] = val;
|
||||
});
|
||||
let maxDmg = 0;
|
||||
lodash.forEach("火水草雷风冰岩".split(""), (key) => {
|
||||
maxDmg = Math.max(data[`属性${key}元素伤害加成`] * 1, maxDmg);
|
||||
});
|
||||
ret.dmgBonus = (maxDmg * 100).toFixed(2);
|
||||
ret.phyBonus = (data[`属性物理伤害加成`] * 100).toFixed(2);
|
||||
|
||||
return ret;
|
||||
},
|
||||
getWeapon(data) {
|
||||
return {
|
||||
name: data['武器名称'],
|
||||
lv: data['武器等级'],
|
||||
refine: data["武器精炼"]
|
||||
}
|
||||
},
|
||||
getArtifact(data) {
|
||||
let ret = {};
|
||||
let get = function (idx, key) {
|
||||
let v = data[`圣遗物${idx}${key}`];
|
||||
let ret = /^([^\d]*)([\d\.\-]*)$/.exec(v);
|
||||
if (ret && ret[1]) {
|
||||
let title = ret[1], val = ret[2];
|
||||
if (artifactMap[title]) {
|
||||
if (artifactMap[title].pct) {
|
||||
val = (val * 100).toFixed(2);
|
||||
}
|
||||
title = artifactMap[title].title;
|
||||
}
|
||||
return [title, val];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
for (let idx = 1; idx <= 5; idx++) {
|
||||
ret[`arti${idx}`] = {
|
||||
name: data[`圣遗物${idx}名称`],
|
||||
type: data[`圣遗物${idx}类型`],
|
||||
main: get(idx, "主词条"),
|
||||
attrs: [
|
||||
get(idx, "副词条1"),
|
||||
get(idx, "副词条2"),
|
||||
get(idx, "副词条3"),
|
||||
get(idx, "副词条4"),
|
||||
]
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getTalent(data) {
|
||||
let ret = {};
|
||||
lodash.forEach({
|
||||
a: 1,
|
||||
e: 2,
|
||||
q: 3
|
||||
}, (idx, key) => {
|
||||
let val = data[`天赋主动名称${idx}`]
|
||||
let regRet = /等级(\d*)$/.exec(val);
|
||||
if (regRet && regRet[1]) {
|
||||
ret[key] = regRet[1] * 1 || 1
|
||||
} else {
|
||||
ret[key] = 1;
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import {attrMark, maxMark, attrMap, usefulAttr} from "../../resources/meta/reliquaries/reliquaries-mark.js";
|
||||
import lodash from "lodash";
|
||||
|
||||
//let meta = Data.readJSON("../../resources/meta/reliquaries", "data.json");
|
||||
|
||||
|
||||
let Reliquaries = {
|
||||
getUseful(char) {
|
||||
let attrKey = usefulAttr[char] || "";
|
||||
@ -78,6 +81,14 @@ let Reliquaries = {
|
||||
return scoreMap[idx][0];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getSet(name) {
|
||||
for (let idx in meta) {
|
||||
if (meta[idx].name === name) {
|
||||
return meta[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1137
resources/meta/reliquaries/data.json
Normal file
1137
resources/meta/reliquaries/data.json
Normal file
File diff suppressed because it is too large
Load Diff
141
tools/reli-data-sprider.js
Normal file
141
tools/reli-data-sprider.js
Normal file
@ -0,0 +1,141 @@
|
||||
import fs from "fs";
|
||||
import cheerio from "cheerio";
|
||||
import lodash from "lodash";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
const _path = process.cwd();
|
||||
|
||||
const artiIdx = {
|
||||
Flower: 1,
|
||||
Plume: 2,
|
||||
Sands: 3,
|
||||
Goblet: 4,
|
||||
Circlet: 5
|
||||
}
|
||||
|
||||
let getCharData = async function (url, key, name = '') {
|
||||
|
||||
url = "https://genshin.honeyhunterworld.com/" + url;
|
||||
console.log('req' + key, url)
|
||||
|
||||
let req = await fetch(url);
|
||||
let txt = await req.text();
|
||||
|
||||
const $ = cheerio.load(txt);
|
||||
let ret = getBasic($, name);
|
||||
|
||||
name = ret.name;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function saveCharData(url, key, name) {
|
||||
|
||||
let data = await getCharData(url, key, name);
|
||||
|
||||
name = name || data.name;
|
||||
|
||||
if (!name) {
|
||||
console.log("角色名不存在" + url);
|
||||
return;
|
||||
}
|
||||
|
||||
let charPath = `${_path}/plugins/miao-plugin/resources/meta/character/${data.name}/`
|
||||
if (!fs.existsSync(charPath)) {
|
||||
fs.mkdirSync(charPath);
|
||||
}
|
||||
|
||||
fs.writeFileSync(`${charPath}data.json`, JSON.stringify(data, "", "\t"));
|
||||
console.log(data.name + "下载完成");
|
||||
}
|
||||
|
||||
function getEffect(txt) {
|
||||
let regRet = /(\d) Piece:/.exec(txt);
|
||||
if (regRet) {
|
||||
return [regRet[1], txt.replace(regRet[0], "").trim().replace(/。$/, "")]
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
async function getSets(id) {
|
||||
const url = `https://genshin.honeyhunterworld.com/db/art/family/a_${id}/?lang=CHS`;
|
||||
let req = await fetch(url);
|
||||
let txt = await req.text();
|
||||
fs.writeFileSync("./test.html", txt);
|
||||
let $ = cheerio.load(txt);
|
||||
|
||||
let sets = $(".wrappercont .add_stat_table:eq(0)");
|
||||
let ret = {}
|
||||
|
||||
sets.find("td").each(function () {
|
||||
let line = $(this);
|
||||
let nRet = /\s*(.*?)\s+\(([^\s]+)/.exec(line.find("span").text());
|
||||
let idRet = /a_(\d+)/.exec(line.find("a").attr("href"));
|
||||
if (nRet && idRet) {
|
||||
ret[`arti${artiIdx[nRet[2]]}`] = {
|
||||
id: idRet[1],
|
||||
name: nRet[1]
|
||||
}
|
||||
}
|
||||
})
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function down() {
|
||||
const url = "https://genshin.honeyhunterworld.com/db/artifact/?lang=CHS";
|
||||
let req = await fetch(url);
|
||||
let txt = await req.text();
|
||||
let $ = cheerio.load(txt);
|
||||
let char = $(".art_stat_table_new");
|
||||
|
||||
let ret = {}
|
||||
let tmp = {};
|
||||
|
||||
char.each(function () {
|
||||
let trs = $(this).find("tr:gt(0)");
|
||||
trs.each(function (idx) {
|
||||
let self = $(this);
|
||||
if (idx % 2 === 0) {
|
||||
let na = self.find("td:eq(2) a")
|
||||
let idRet = /a_(\d+)/.exec(na.attr("href"))
|
||||
if (idRet) {
|
||||
tmp = {
|
||||
id: idRet[1],
|
||||
name: na.text(),
|
||||
sets: {},
|
||||
effect: {}
|
||||
}
|
||||
} else {
|
||||
tmp = {effect: {}}
|
||||
}
|
||||
}
|
||||
let et = getEffect(self.find(`td:eq(${idx % 2 === 0 ? 4 : 1})`).text());
|
||||
if (et && et[0]) {
|
||||
tmp.effect[et[0]] = et[1];
|
||||
}
|
||||
if (idx % 2 === 1 && tmp.id) {
|
||||
ret[tmp.id] = tmp;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
for (let idx in ret) {
|
||||
let ds = ret[idx];
|
||||
|
||||
ds.sets = await getSets(ds.id);
|
||||
console.log(`arti ${ds.id}:${ds.name} Done`);
|
||||
}
|
||||
|
||||
let filePath = `${_path}/plugins/miao-plugin/resources/meta/reliquaries/`
|
||||
fs.writeFileSync(`${filePath}data.json`, JSON.stringify(ret, "", "\t"));
|
||||
}
|
||||
|
||||
//await saveCharData("https://genshin.honeyhunterworld.com/db/char/ayaka/?lang=CHS", "ayaka");
|
||||
|
||||
|
||||
await down();
|
||||
|
||||
|
||||
|
||||
|
||||
|
89
tools/reli-img-download.js
Normal file
89
tools/reli-img-download.js
Normal file
@ -0,0 +1,89 @@
|
||||
import {Data} from "../components/index.js";
|
||||
import lodash from "lodash";
|
||||
import fs from "fs";
|
||||
import request from "request";
|
||||
|
||||
const _path = process.cwd() + "/plugins/miao-plugin/resources/meta/reliquaries/";
|
||||
|
||||
let relis = Data.readJSON(_path, 'data.json');
|
||||
|
||||
|
||||
for(let idx in relis){
|
||||
|
||||
}
|
||||
|
||||
|
||||
lodash.forEach(readDir, (c) => {
|
||||
|
||||
console.log(c);
|
||||
|
||||
if (!fs.existsSync(`${_cRoot}/${c}/data.json`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let char = Data.readJSON(`${_cRoot}/${c}/`, 'data.json');
|
||||
|
||||
if (char.name) {
|
||||
// 正面
|
||||
|
||||
// 角色条
|
||||
img(char, char.imgs.profile, "profile.png");
|
||||
// 名片
|
||||
img(char, char.imgs.party, "party.png");
|
||||
// img(char, char.imgs.char, "char.png");
|
||||
// 立绘-竖版
|
||||
img(char, char.imgs.gacha_card, "gacha_card.png");
|
||||
// 立绘
|
||||
img(char, char.imgs.gacha_splash, "gacha_splash.png");
|
||||
// 正面像
|
||||
img(char, char.imgs.face, "face.png");
|
||||
img(char, char.imgs.side, "face.png");
|
||||
|
||||
// 天赋
|
||||
if (char.talent) {
|
||||
img(char, char.talent.a.icon, "talent_a.png");
|
||||
img(char, char.talent.e.icon, "talent_e.png");
|
||||
img(char, char.talent.q.icon, "talent_q.png");
|
||||
}
|
||||
// 被动天赋
|
||||
lodash.forEach(char.passive, (p, idx) => {
|
||||
img(char, p.icon, `passive_${idx}.png`);
|
||||
});
|
||||
|
||||
// 命座
|
||||
lodash.forEach(char.cons, (con, idx) => {
|
||||
img(char, con.icon, `cons_${idx}.png`)
|
||||
});
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
let cacheFile = async function () {
|
||||
|
||||
let cacheFn = async function (file) {
|
||||
if (fs.existsSync(`${_cRoot}/${file.file}`)) {
|
||||
console.log(`已存在,跳过 ${file.file}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
let stream = fs.createWriteStream(`${_cRoot}/${file.file}`);
|
||||
await request("https://genshin.honeyhunterworld.com/" + file.url).pipe(stream);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
stream.on('finish', resolve)
|
||||
});
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
console.log(`下载成功: ${file.file}`);
|
||||
return true;
|
||||
};
|
||||
|
||||
console.log('开始下载');
|
||||
await Data.asyncPool(5, imgs, cacheFn);
|
||||
|
||||
}
|
||||
|
||||
await cacheFile();
|
||||
console.log('下载成功');
|
Loading…
Reference in New Issue
Block a user