diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b2ac17c..f35c1427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,22 @@ -# 1.8.2 +# 1.8.3 + +* `#刻晴` 角色卡片功能升级 + * `#老婆设置刻晴,心海`不再检查是否具有角色或展示在米游社展柜 + * `#刻晴` 角色卡片优先使用面板数据进行展示,无面板数据时使用米游社数据 + * 在未能获取到角色数据时也会展示角色卡片 + * 角色卡片后续会进行样式升级,按需展示更多内容 +* `#深渊出场率`增加楼层排序,以防止服务侧数据乱序导致顺序错乱 +* B服面板的天赋与皇冠信息现在可以正确的展示了 + +# 1.8.1~1.8.2 * `#喵喵帮助`增加对自定义配置文件的支持 * 已有配置文件可更名为help-cfg.js,防止后续更新冲突,后续会支持更多配置项 * 在默认配置中增加部分新帮助命令 -* `#喵喵日历`现在可通过`#日历 #日历列表`触发 -* 修正胡桃E伤害计算错误 - -# 1.8.1 - * 增加`#添加刻晴图像`命令,感谢 **@叶** * 可通过命令上传添加指定角色图片,上传至 **resources/character-img/刻晴/upload** * 请将图像与命令一同发送,后续会支持at图像及命令后发送图像 -* 部分功能的页面文案及功能优化 +* `#喵喵日历`现在可通过`#日历 #日历列表`触发 # 1.8.0 diff --git a/apps/character/avatar-card.js b/apps/character/avatar-card.js index 62070844..b32fff5f 100644 --- a/apps/character/avatar-card.js +++ b/apps/character/avatar-card.js @@ -1,8 +1,8 @@ -import { Character } from "../../components/models.js"; +import { Artifact, Character } from "../../components/models.js"; import { Cfg } from "../../components/index.js"; import lodash from "lodash"; import { segment } from "oicq"; -import Common from "../../components/Common.js"; +import { Common, Profile } from "../../components/index.js"; //角色昵称 let nameID = ""; @@ -26,42 +26,45 @@ export async function renderAvatar(e, avatar, render, renderType = "card") { return false; } + let MysApi = await e.getMysApi({ auth: "all", targetType: Cfg.get("char.queryOther", true) ? "all" : "self", cookieType: "all", actionName: "查询信息" }); + if (!MysApi) return true; - let charData = await MysApi.getCharacter(); - if (!charData) return true; + let uid = e.targetUser.uid; - let avatars = charData.avatars; - let length = avatars.length; - char.checkAvatars(avatars); - avatars = lodash.keyBy(avatars, "id"); - if (!avatars[char.id]) { - let name = lodash.truncate(e.sender.card, { length: 8 }); - if (length > 8) { - e.reply([segment.at(e.user_id, name), `\n没有${e.msg}`]); - } else { - e.reply([segment.at(e.user_id, name), "\n请先在米游社展示该角色"]); - } - return true; + let profile = await Profile.get(uid, char.id, true); + if (profile) { + // 优先使用Profile数据 + avatar = profile; + } else { + // 使用Mys数据兜底 + let charData = await MysApi.getCharacter(); + if (!charData) return true; + + let avatars = charData.avatars; + let length = avatars.length; + char.checkAvatars(avatars); + avatars = lodash.keyBy(avatars, "id"); + avatar = avatars[char.id] || { id: char.id, name: char.name, detail: false }; } - avatar = avatars[char.id]; } return await renderCard(e, avatar, render, renderType); - } // 渲染角色卡片 async function renderCard(e, avatar, render, renderType = "card") { + + let talent = await getTalent(e, avatar); // 计算皇冠个数 - let crownNum = lodash.filter(lodash.map(talent, (d) => d.level_original), (d) => d >= 10).length; + let crownNum = lodash.filter(lodash.map(talent, (d) => d.original), (d) => d >= 10).length; let uid = e.uid || (e.targetUser && e.targetUser.uid); @@ -97,54 +100,40 @@ async function renderCard(e, avatar, render, renderType = "card") { //获取角色技能数据 async function getTalent(e, avatars) { - - let MysApi = await e.getMysApi({ - auth: "all", - targetType: Cfg.get("char.queryOther", true) ? "all" : "self", - cookieType: "all", - actionName: "查询信息" - }); - if (!MysApi && !MysApi.isSelfCookie) return {}; - - let skill = {}; - - let skillRes = await MysApi.getAvatar(avatars.id); - - if (skillRes && skillRes.skill_list) { - skill.id = avatars.id; - let skill_list = lodash.orderBy(skillRes.skill_list, ["id"], ["asc"]); - - for (let val of skill_list) { - val.level_original = val.level_current; - if (val.name.includes("普通攻击")) { - skill.a = val; - continue; - } - if (val.max_level >= 10 && !skill.e) { - skill.e = val; - continue; - } - if (val.max_level >= 10 && !skill.q) { - skill.q = val; - - } - } - if (avatars.actived_constellation_num >= 3) { - if (avatars.constellations[2].effect.includes(skill.e.name)) { - skill.e.level_current += 3; - } else if (avatars.constellations[2].effect.includes(skill.q.name)) { - skill.q.level_current += 3; - } - } - if (avatars.actived_constellation_num >= 5) { - if (avatars.constellations[4].effect.includes(skill.e.name)) { - skill.e.level_current += 3; - } else if (avatars.constellations[4].effect.includes(skill.q.name)) { - skill.q.level_current += 3; + let talent = {}, cons = 0, char = Character.get(avatars.id), mode = "level"; + if (avatars.dataSource && avatars.talent) { + // profile模式 + talent = avatars.talent || {}; + cons = avatars.cons || 0; + } else { + let MysApi = await e.getMysApi({ + auth: "all", + targetType: Cfg.get("char.queryOther", true) ? "all" : "self", + cookieType: "all", + actionName: "查询信息" + }); + if (!MysApi && !MysApi.isSelfCookie) return {}; + let skillRes = await MysApi.getAvatar(avatars.id); + cons = avatars.actived_constellation_num + mode = "original"; + if (skillRes && skillRes.skill_list) { + let skill_list = lodash.orderBy(skillRes.skill_list, ["id"], ["asc"]); + for (let val of skill_list) { + if (val.name.includes("普通攻击")) { + talent.a = val; + continue; + } + if (val.max_level >= 10 && !talent.e) { + talent.e = val; + continue; + } + if (val.max_level >= 10 && !talent.q) { + talent.q = val; + } } } } - return skill; + return char.getAvatarTalent(talent, cons, mode); } @@ -181,54 +170,41 @@ async function pokeCharacter(e, { render }) { function getCharacterData(avatars) { let list = []; let set = {}; - let setArr = []; - let text1 = ""; - let text2 = ""; - + let artiEffect = []; + let w = avatars.weapon || {}; let weapon = { type: "weapon", - name: avatars.weapon.name, - showName: genshin.abbr[avatars.weapon.name] ? genshin.abbr[avatars.weapon.name] : avatars.weapon.name, - level: avatars.weapon.level, - affix_level: avatars.weapon.affix_level, - }; + name: w.name || "", + showName: genshin.abbr[w.name] || w.name || "", + level: w.level || 1, + affix: w.affix || w.affix_level || 0 + } - for (let val of avatars.reliquaries) { - if (set[val.set.name]) { - set[val.set.name]++; + let artis = avatars.artis || avatars.reliquaries; - if (set[val.set.name] == 2) { - if (text1) { - text2 = "2件套:" + val.set.affixes[0].effect; - } else { - text1 = "2件套:" + val.set.affixes[0].effect; + if (artis) { + lodash.forEach(artis, (val) => { + let setCfg = Artifact.getSetByArti(val.name); + if (!setCfg) { + return; + } + let setName = setCfg.name; + if (set[setName]) { + set[setName]++; + if (set[setName] === 2) { + artiEffect.push("2件套:" + setCfg.effect['2']) } + if (set[setName] === 4) { + artiEffect.push("4件套:" + setCfg.name); + } + } else { + set[setName] = 1; } + }) - if (set[val.set.name] == 4) { - text2 = "4件套:" + val.set.name; - } - } else { - set[val.set.name] = 1; + if (artiEffect.length === 0) { + artiEffect = ["无套装效果"]; } - - list.push({ - type: "reliquaries", - name: val.name, - level: val.level, - }); - } - - for (let val of Object.keys(set)) { - setArr.push({ - name: val, - num: set[val], - showName: genshin.abbr[val] ? genshin.abbr[val] : val, - }); - } - - if (avatars.reliquaries.length >= 2 && !text1) { - text1 = "无套装效果"; } if (avatars.id == "10000005") { @@ -241,14 +217,12 @@ function getCharacterData(avatars) { return { name: avatars.name, showName: genshin.abbr[avatars.name] ? genshin.abbr[avatars.name] : avatars.name, - level: avatars.level, + level: avatars.lv || avatars.level, fetter: avatars.fetter, - actived_constellation_num: avatars.actived_constellation_num, + cons: avatars.cons || avatars.actived_constellation_num, weapon, - text1, - text2, - reliquaries, - set: setArr, + artiEffect, + reliquaries }; } @@ -280,4 +254,8 @@ export async function getAvatarList(e, type, MysApi) { let sortKey = "level,fetter,weapon_level,rarity,weapon_rarity,cons,weapon_affix_level"; list = lodash.orderBy(list, sortKey, lodash.repeat("desc,", sortKey.length).split(",")); return list; +} + +export function checkWifeType(id, type) { + return genshin.wifeData[type].includes(Number(id)); } \ No newline at end of file diff --git a/apps/character/avatar-wife.js b/apps/character/avatar-wife.js index d37da4be..3a74e1a7 100644 --- a/apps/character/avatar-wife.js +++ b/apps/character/avatar-wife.js @@ -1,8 +1,8 @@ //#老婆 import lodash from "lodash"; import { Cfg } from "../../components/index.js"; -import {Character} from "../../components/models.js"; -import { getAvatarList, renderAvatar } from "./avatar-card.js"; +import { Character } from "../../components/models.js"; +import { checkWifeType, getAvatarList, renderAvatar } from "./avatar-card.js"; const relationMap = { wife: { @@ -68,12 +68,10 @@ export async function wife(e, { render, User }) { cookieType: "all", actionName: "查询信息" }); - if (!MysApi || !MysApi.selfUser) { return true; } let selfUser = MysApi.selfUser; - let selfMysUser = await selfUser.getMysUser(); let isSelf = true; if (!selfMysUser || selfMysUser.uid !== MysApi.targetUser.uid) { @@ -131,20 +129,20 @@ export async function wife(e, { render, User }) { } else { wifeList = lodash.map(wifeList, (name) => { let char = Character.get(name); - if (char) { + if (char && checkWifeType(char.id, targetCfg.type)) { return char.name; } }); wifeList = lodash.filter(lodash.uniq(wifeList), (d) => !!d); + /* avatarList = await getAvatarList(e, targetCfg.type, MysApi); avatarList = lodash.map(avatarList, (avatar) => avatar.name); avatarList = lodash.filter(avatarList, (d) => !!d); addRet = lodash.intersection(avatarList, wifeList); + */ + addRet = wifeList; if (addRet.length === 0) { e.reply(`在可选的${targetCfg.keyword[0]}列表中未能找到 ${actionParam} ~`); - if (!MysApi.isSelfCookie) { - e.reply("请确认已在米游社展示对应角色,也可以绑定Cookie以查询所有角色.."); - } return true; } } @@ -156,12 +154,10 @@ export async function wife(e, { render, User }) { case "是": case "是谁": // 查看当前选择老婆 - if (!isSelf) { e.reply("只能查看自己的哦~"); return true; } - wifeList = await selfUser.getCfg(`wife.${targetCfg.key}`, []); if (wifeList && wifeList.length > 0) { e.reply(`你的${targetCfg.keyword[0]}是:${wifeList.join(",")}`); diff --git a/apps/character/profile-detail.js b/apps/character/profile-detail.js index a7120d1f..fc0c53d4 100644 --- a/apps/character/profile-detail.js +++ b/apps/character/profile-detail.js @@ -59,7 +59,7 @@ export async function renderProfile(e, char, render, mode = "profile", params = }; - let { artis,totalMark, totalMarkClass,usefulMark } = getArtis(char.name, profile.artis); + let { artis, totalMark, totalMarkClass, usefulMark } = getArtis(char.name, profile.artis); let enemyLv = await selfUser.getCfg(`char.enemyLv`, 91); @@ -105,6 +105,7 @@ export async function renderProfile(e, char, render, mode = "profile", params = cons: char.cons, name: char.name, elem: char.elem, + talent: char.getAvatarTalent(profile.talent, profile.cons), dmgData, dmgMsg, dmgRet: dmgCalc.dmgRet, diff --git a/apps/stat.js b/apps/stat.js index fb41714d..652b5467 100644 --- a/apps/stat.js +++ b/apps/stat.js @@ -120,10 +120,12 @@ export async function abyssPct(e, { render }) { } }); - lodash.forEach(abyssData.data, (floorData) => { + let data = abyssData.data; + data = lodash.sortBy(data, "floor"); + + lodash.forEach(data, (floorData) => { let floor = { floor: floorData.floor, - }; let avatars = []; lodash.forEach(floorData.avatarUsage, (ds) => { diff --git a/components/Profile.js b/components/Profile.js index cb98f01d..bd2f9b5c 100644 --- a/components/Profile.js +++ b/components/Profile.js @@ -116,7 +116,15 @@ let Profile = { return false; }, - async get(uid, charId) { + async get(uid, charId, onlyAvailable = false) { + if (onlyAvailable) { + let data = await Profile.get(uid, charId); + if (data && data.dataSource && data.dataSource !== "input") { + return data; + } + return false; + } + let data = Profile._get(uid, charId); let Serv = getServ(uid); if (Serv.getCharData && data && data.id) { diff --git a/components/models/Artifact.js b/components/models/Artifact.js index 219c89b8..91b72ee5 100644 --- a/components/models/Artifact.js +++ b/components/models/Artifact.js @@ -3,6 +3,17 @@ import { attrValue, attrNameMap, attrMap, mainAttr, subAttr, usefulAttr } import { Character } from "../models.js"; import lodash from "lodash"; import Format from "../Format.js"; +import _Data from "../Data.js"; + +let _path = process.cwd(); +let artis = _Data.readJSON(`${_path}/plugins/miao-plugin/resources/meta/reliquaries/`, "data.json") || {}; + +let artisMap = {} + +lodash.forEach(artis, (ds) => { + artisMap[ds.name] = ds; +}) + let charCfg = {}; let Artifact = { @@ -53,6 +64,7 @@ let Artifact = { }; return charCfg[name]; }, + getMaxAttr(charAttr = {}, list2 = [], maxLen = 1, banAttr = "") { let tmp = []; lodash.forEach(list2, (attr) => { @@ -66,6 +78,7 @@ let Artifact = { lodash.forEach(tmp, (ds) => ret.push(ds.attr)); return ret.slice(0, maxLen); }, + getMaxMark(attrWeight) { let ret = {}; for (let idx = 1; idx <= 5; idx++) { @@ -90,6 +103,7 @@ let Artifact = { } return ret; }, + getAttr(ds) { let title = ds[0] let attr = attrNameMap[title]; @@ -100,6 +114,7 @@ let Artifact = { } return attr; }, + getAttrMark(attrMark, ds) { if (!ds || !ds[1]) { return 0; @@ -108,6 +123,7 @@ let Artifact = { let val = ds[1]; return (attrMark[attr] || 0) * val; }, + getMark(charCfg, posIdx, mainAttr, subAttr) { let ret = 0; let { mark, maxMark, weight } = charCfg; @@ -136,6 +152,7 @@ let Artifact = { }); return ret; }, + getMarkClass(mark) { let pct = mark; let scoreMap = [["D", 10], ["C", 16.5], ["B", 23.1], ["A", 29.7], ["S", 36.3], ["SS", 42.9], ["SSS", 49.5], ["ACE", 56.1], ["ACE²", 66]]; @@ -145,20 +162,24 @@ let Artifact = { } } }, - getSet(name) { - for (let idx in meta) { - if (meta[idx].name === name) { - return meta[idx]; + + getSetByArti(name) { + for (let idx in artisMap) { + for (let idx2 in artisMap[idx].sets) { + if (artisMap[idx].sets[idx2].name === name) { + return artisMap[idx]; + } } } + return false; }, + getMeta() { return { attrMap } }, - formatArti(ds, markCfg = false, isMain = false) { if (lodash.isArray(ds[0])) { let ret = []; diff --git a/components/models/Character.js b/components/models/Character.js index 228868b0..95155cff 100644 --- a/components/models/Character.js +++ b/components/models/Character.js @@ -99,6 +99,50 @@ class Character extends Base { } } + getAvatarTalent(talent = {}, cons = 0, mode = "level") { + let ret = {}; + let consTalent = this.getConsTalent(); + lodash.forEach(['a', 'e', 'q'], (key) => { + let ds = talent[key]; + if (ds) { + let level; + if (lodash.isNumber(ds)) { + level = ds; + } else { + level = mode === "level" ? ds.level || ds.level_current || ds.original || ds.level_original : + ds.original || ds.level_original || ds.level || ds.level_current; + } + if (mode === "level") { + // 基于level计算original + ret[key] = { + level, + original: (key !== "a" && cons >= consTalent[key]) ? (level - 3) : level + } + } else { + // 基于original计算level + ret[key] = { + original: level, + level: (key !== "a" && cons >= consTalent[key]) ? (level + 3) : level + } + } + + + } + }) + return ret; + } + + getConsTalent() { + let e = this.talent.e.name, + q = this.talent.q.name; + let c3 = this.cons['3'].desc, + c5 = this.cons['5'].desc; + return { + e: c3.includes(e) ? 3 : 5, + q: c5.includes(q) ? 5 : 3, + } + } + get weaponType() { const map = { sword: "单手剑", diff --git a/resources/character/card.css b/resources/character/card.css index 51b1d059..81bd12c1 100644 --- a/resources/character/card.css +++ b/resources/character/card.css @@ -419,4 +419,17 @@ body.bottom_mode { line-height: 20px; font-size: 10px; } +.no-info { + position: absolute; + padding: 5px 10px; + bottom: 30px; + right: 10px; + font-size: 16px; + background: rgba(0, 0, 0, 0.5); + text-shadow: 1px 1px 1px #000; + border-radius: 5px; +} +.bottom_mode .no-info { + bottom: 25px; +} /*# sourceMappingURL=card.css.map */ \ No newline at end of file diff --git a/resources/character/card.html b/resources/character/card.html index 7cf7365b..f1301769 100644 --- a/resources/character/card.html +++ b/resources/character/card.html @@ -7,12 +7,14 @@ +
+ {{if level}}
ID:{{uid}}
{{ds.name}} {{actived_constellation_num}}命 + class="cons cons-{{cons}}">{{cons}}命
Lv.{{level}} ❤{{fetter}} @@ -24,11 +26,11 @@

Lv.{{weapon.level}}

-

{{weapon.affix_level}}

+

{{weapon.affix}}

- Lv.{{weapon.level}} 精{{weapon.affix_level}} - 精{{weapon.affix_level}} + Lv.{{weapon.level}} 精{{weapon.affix}} + 精{{weapon.affix}} {{weapon.name}}

@@ -36,7 +38,7 @@ {{ if talent.a }}
{{each talentMap name key}} -
{{name}}: {{ talent[key].level_current}}
+
{{name}}: {{ talent[key].level}}
{{/each}}
{{else}} @@ -45,10 +47,17 @@
{{/if}}
-
{{text1|| "-"}}
-
{{text2 || "-"}}
+
{{artiEffect[0]|| "-"}}
+
{{artiEffect[1] || "-"}}
+ {{else}} +
+
ID:{{uid}}
+ {{ds.name}} +
+
未能获取到角色信息,请将角色放置在米游社角色展柜中
+ {{/if}}
diff --git a/resources/character/card.less b/resources/character/card.less index 25cce606..007991a9 100644 --- a/resources/character/card.less +++ b/resources/character/card.less @@ -506,4 +506,19 @@ body.bottom_mode { text-shadow: 1px 1px 1px #000; line-height: 20px; font-size: 10px; +} + +.no-info { + position: absolute; + padding: 5px 10px; + bottom: 30px; + right: 10px; + font-size: 16px; + background: rgba(0, 0, 0, 0.5); + text-shadow: 1px 1px 1px #000; + border-radius: 5px; +} + +.bottom_mode .no-info { + bottom: 25px; } \ No newline at end of file diff --git a/resources/character/detail.html b/resources/character/detail.html index 114d58ab..e3e16ed2 100644 --- a/resources/character/detail.html +++ b/resources/character/detail.html @@ -5,7 +5,6 @@ {{/block}} {{set weapon = data.weapon}} -{{set talent = data.talent}} {{set dataSource = data.dataSource}} @@ -21,11 +20,11 @@ {{each talentMap tName key}}
+ {{talent[key].level > talent[key].original ? `talent-plus`:``}} + {{talent[key].original == 10 ? `talent-crown`:``}}">
- {{talent[key].level_current}} + {{talent[key].level}}
{{/each}}