diff --git a/CHANGELOG.md b/CHANGELOG.md index 738d4154..9adc9bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,32 @@ -# 2.4.8 +# 2.5.1 dev -* 星铁面板支持面板变换功能 -* 面板变换支持更换圣遗物套装,例如`#甘雨换乐团`、`#镜流换快枪手封印站` -* 微调面板页面的部分样式 +* 重构Models的结构,尚未完全完成,功能可能不稳定 +* 原神的面板数据迁移至 **/data/PlayerData/gs** -# 2.4.1 ~ 2.4.7 +# 2.5.0 * 初步支持星铁面板数据获取与展示 * 可使用`#星铁更新面板`来获取面板信息,通过`#希儿面板`来进行查看 - * 星铁面板展示圣遗物评分,评分功能尚未完全完成,分值与样式不为最终版本 - * 部分角色的伤害计算,以及圣遗物评分功能仍在补全中 + * 星铁面板展示圣遗物评分,评分功能尚未完全完成 * 星铁面板天赋展示更新,支持展示行迹信息 + * 初步增加星铁的排名功能 **@Simplxss** + * 增加`#星铁日历`功能 **@Aluxes** + * 星铁面板支持面板变换功能 * 请配合使用Miao-Yunzai 3.1.0可达到最佳效果 * Miao-Yunzai可使用`*`来代填`#星铁`前缀,能区分游戏使用不同UID * 其他Yunzai版本出现原神与星铁UID混淆情况为正常情况,请手动切换UID或命令后附加UID查询 -* 角色数据及资源更新 - * 增加原神4.0~4.2的角色信息,可通过`#水神天赋`、`#水神图鉴`查看 - * 更新星铁1.2~1.3的角色数据与资源 * 伤害计算更新 * 增加林尼、卡夫卡、银狼的伤害计算**@Aluxes** * 增加原神4.0相关的武器计算 **@SmallK111407** * 增加菲米尼、符玄、玲可、三月七、娜塔莎、罗刹、黑塔的伤害计算 **@Aluxes** -* 初步增加星铁的排名功能 **@Simplxss** +* 面板功能升级 + * 面板变换支持更换圣遗物套装,例如`#甘雨换乐团`、`#镜流换快枪手封印站` + * 增加`#重载面板`功能,用于手工修改面板数据后主动读取 + * 微调面板页面的部分样式 +* 角色数据及资源更新 + * 增加原神4.0~4.2的角色信息,可通过`#水神天赋`、`#水神图鉴`查看 + * 更新星铁1.2~1.3的角色数据与资源 * 增加`#喵喵api`命令,用于查看喵ApiToken的有效期 -* 增加`#星铁日历`功能 **@Aluxes** -* 增加`#重载面板`功能,用于手工修改面板数据后主动读取 -* 停用旧面板格式数据,非AttrIDs格式的数据不会展示,部分角色面板数据不展示是正常情况,重新更新面板数据即可 * 一些已知问题修复 # 2.4.0 diff --git a/apps/character/AvatarCard.js b/apps/character/AvatarCard.js index ea94d581..ba955c78 100644 --- a/apps/character/AvatarCard.js +++ b/apps/character/AvatarCard.js @@ -53,7 +53,7 @@ let Avatar = { data = avatar.getDetail() data.imgs = char.imgs data.source = avatar._source - data.artis = avatar.getArtisDetail() + data.artis = avatar.getArtisDetail(true) data.updateTime = moment(new Date(avatar._time)).format('MM-DD HH:mm') if (data.hasTalent) { data.talent = avatar.talent diff --git a/apps/profile/ProfileStat.js b/apps/profile/ProfileStat.js index f297984b..ebd05afa 100644 --- a/apps/profile/ProfileStat.js +++ b/apps/profile/ProfileStat.js @@ -9,6 +9,9 @@ const ProfileStat = { async avatarList (e) { return ProfileStat.render(e, true) }, + + // 渲染 + // isAvatarList true:练度统计 false角色列表 async render (e, isAvatarList = false) { // 缓存时间,单位小时 let msg = e.msg.replace('#', '').trim() diff --git a/models/Avatar.js b/models/Avatar.js index 3eb93b31..8f54e3db 100644 --- a/models/Avatar.js +++ b/models/Avatar.js @@ -1,19 +1,259 @@ import lodash from 'lodash' -import { Data } from '#miao' -import { ProfileDmg } from './index.js' -import AvatarBase from './avatar/AvatarBase.js' +import { Data, Format } from '#miao' +import { Character, ProfileDmg, Weapon } from './index.js' +import Base from './Base.js' import Attr from './attr/Attr.js' import Artis from './artis/Artis.js' import ProfileAvatar from './avatar/ProfileAvatar.js' import ArtisMark from './artis/ArtisMark.js' +import moment from 'moment' -export default class Avatar extends AvatarBase { +const charKey = 'name,abbr,sName,star,imgs,face,side,gacha,weaponTypeName'.split(',') + +export default class Avatar extends Base { constructor (ds = {}, game = 'gs') { - super(ds, game) + super() + let char = Character.get({ id: ds.id, elem: ds.elem }) + if (!char) { + return + } + this.id = char.id + this.char = char + this.game = char.game || game + this._mysArtis = new Artis(this.game) this._artis = new Artis(this.game, true) } + + get hasTalent () { + return this.talent && !lodash.isEmpty(this.talent) && !!this._talent + } + + get name () { + return this.char?.name || '' + } + + get costume () { + let costume = this._costume + if (lodash.isArray(costume)) { + costume = costume[0] + } + return costume + } + + get originalTalent () { + return lodash.mapValues(this.talent, (ds) => ds.original) + } + + // 已经到达当前等级的最大天赋 + get isMaxTalent () { + let maxLv = [1, 2, 4, 6, 8, 10]?.[this.promote - 1] || 10 + let minTalent = lodash.min(lodash.map(this.talent, (ds) => ds.original)) + if (this.name === '卡维') { + console.log( + 'kaka', maxLv, minTalent, this.promote + ) + } + return minTalent >= maxLv + } + + get mysArtis () { + return this._mysArtis + } + + /** + * 获取圣遗物套装属性 + * @returns {boolean|*|{imgs: *[], names: *[], sets: {}, abbrs: *[], sName: string, name: (string|*)}|{}} + */ + get artisSet () { + return this.mysArtis.getSetData() + } + + get dataSource () { + return { + enka: 'Enka.Network', + miao: '喵喵Api', + mgg: 'MiniGG-Api', + hutao: 'Hutao-Enka', + mys: '米游社', + homo: 'Mihomo' + }[this._source] || this._source + } + + get updateTime () { + let time = this._time + if (!time) { + return '' + } + if (lodash.isString(time)) { + return moment(time).format('MM-DD HH:mm') + } + if (lodash.isNumber(time)) { + return moment(new Date(time)).format('MM-DD HH:mm') + } + return '' + } + + _get (key) { + if (charKey.includes(key)) { + return this.char[key] + } + } + + + /** + * 设置角色基础数据 + * @param ds + * @param source + */ + setBasic (ds = {}, source = '') { + const now = this._now || (new Date()) * 1 + this.level = ds.lv || ds.level || this.level || 1 + this.cons = ds.cons || this.cons || 0 + this.fetter = ds.fetter || this.fetter || 0 + this._costume = ds.costume || this._costume || 0 + this.elem = ds.elem || this.elem || this.char.elem || '' + this.promote = Math.max((ds.promote ? ds.promote : this.promote) * 1 || 0, Attr.calcPromote(this.level)) + this.trees = this.trees || [] + this._source = ds._source || this._source || '' // 数据源 + this._time = ds._time || this._time || now // 面板最后更新时间 + this._update = ds._update || this._update || ds._time || now //最后更新时间,包括mys + this._talent = ds._talent || this._talent || ds._time || now // 最后天赋更新时间,包括mys + + if (ds.trees) { + this.setTrees(ds.trees) + } + + // 存在数据源时更新时间 + if (source) { + this._update = now + if (source !== 'mys') { + this._source = source + this._time = now + } else { + this._source = this._source || source + this._time = this._source !== 'mys' ? (this._time || now) : now + } + } + } + + // 星铁的行迹数据 + setTrees (ds) { + this.trees = [] + let prefix = '' + let map = {} + lodash.forEach(this.char?.detail?.tree || {}, (ds, key) => { + let ret = /(\d{4})(\d{3})/.exec(key) + if (ret && ret[1] && ret[2]) { + prefix = prefix || ret[1] + map[ret[2]] = key + } + }) + if (prefix) { + for (let i = 0; i <= 3; i++) { + map[`10${i}`] = `${prefix}10${i}` + } + } + lodash.forEach(ds, (id) => { + let ret = /\d{4}(\d{3})/.exec(id) + this.trees.push(map[ret?.[1] || id] || id) + }) + } + + // 设置武器 + setWeapon (ds = {}) { + let w = Weapon.get(ds.name || ds.id, this.game) + if (!w) { + return false + } + this.weapon = { + id: ds.id || w.id, + name: ds.name || w.name, + level: ds.level || ds.lv || 1, + promote: lodash.isUndefined(ds.promote) ? Attr.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0), + affix: ds.affix, + ...w.getData('star,abbr,type,img') + } + if (this.weapon.level < 20) { + this.weapon.promote = 0 + } + } + + // 获取武器详情信息 + getWeaponDetail () { + let ret = { + ...this.weapon + } + if (!ret.id) { + return {} + } + let wData = Weapon.get(ret.id, this.game) + ret.splash = wData.imgs.gacha + let wAttr = wData.calcAttr(ret.level, ret.promote) + let attrs = {} + if (this.isSr) { + lodash.forEach(wAttr, (val, key) => { + attrs[key] = Format.comma(val, 1) + }) + } else if (this.isGs) { + attrs.atkBase = Format.comma(wAttr.atkBase, 1) + if (wAttr?.attr?.key) { + let keyType = { + mastery: 'comma' + } + attrs[wAttr.attr.key] = Format[keyType[wAttr.attr.key] || 'pct'](wAttr.attr.value, 1) + } + } + ret.attrs = attrs + ret.desc = wData.getAffixDesc(ret.affix) + return ret + } + + // 设置天赋 + setTalent (ds = false, mode = 'original', updateTime = '') { + const now = this._now || (new Date()) * 1 + if (ds) { + let ret = this.char.getAvatarTalent(ds, this.cons, mode) + if (ret) { + this.talent = ret || this.talent + // 设置天赋更新时间 + this._talent = ds._talent || this._talent || ds._time || now + } + } + if (updateTime) { + this._talent = now + } + } + + getProfile () { + if (!this.isProfile) { + return false + } + return this + } + + // 判断当前profileData是否具备有效圣遗物信息 + hasArtis () { + return this.isProfile && this.artis.length > 0 + } + + // 获取数据详情 + getDetail (keys = '') { + let imgs = this.char.getImgs(this.costume) + if (this.isGs) { + return { + ...(this.getData(keys || 'id,name,level,star,cons,fetter,elem,abbr,weapon,talent,artisSet') || {}), + ...Data.getData(imgs, 'face,qFace,side,gacha') + } + } else { + return { + ...(this.getData(keys || 'id,name,level,star,cons,elem,abbr,weapon,talent,artisSet,trees') || {}), + ...Data.getData(imgs, 'face,qFace,gacha,preview') + } + } + } + get isAvatar () { return true } @@ -25,7 +265,7 @@ export default class Avatar extends AvatarBase { // profile.hasData 别名 get hasData () { - return !!(this.level > 1 || this?.weapon?.name || this?.talent?.a) + return !!(this.level > 1 || this?.weapon?.name) } get imgs () { @@ -52,8 +292,19 @@ export default class Avatar extends AvatarBase { return profile } + setAvatarBase (ds, source = '') { + this._now = new Date() * 1 + this.setBasic(ds, source) + ds.weapon && this.setWeapon(ds.weapon) + ds.talent && this.setTalent(ds.talent, 'original', source) + let artis = ds.mysArtis || ds.artis + // 只要具备圣遗物信息,就更新mysArtis + this._mysArtis.setArtisData(artis) + delete this._now + } + setAvatar (ds, source = '') { - super.setAvatar(ds, source) + this.setAvatarBase(ds, source) if (ds.artis && source !== 'mys') { this._artis.setArtisData(ds.artis) } @@ -101,8 +352,11 @@ export default class Avatar extends AvatarBase { 'name,id,elem,level,promote,cons,talent:originalTalent,trees' let ret = { ...this.getData(keys), - weapon: Data.getData(this.weapon, this.isGs ? 'name,level,promote,affix' : 'id,level,promote,affix'), - artis: this.artis.toJSON() + weapon: Data.getData(this.weapon, this.isGs ? 'name,level,promote,affix' : 'id,level,promote,affix') + } + let artis = this.artis.toJSON() + if (!lodash.isEmpty(artis)) { + ret.artis = artis } if (!this.mysArtis.isSameArtis(this.artis)) { ret.mysArtis = this.mysArtis.toJSON() @@ -112,4 +366,8 @@ export default class Avatar extends AvatarBase { ...this.getData('_source,_time,_update,_talent') } } + + getArtisDetail (mysArtis = false) { + return (mysArtis ? this.mysArtis : this.artis).getDetail() + } } diff --git a/models/Player.js b/models/Player.js index 7fee6bfa..ec2388ae 100644 --- a/models/Player.js +++ b/models/Player.js @@ -178,6 +178,10 @@ export default class Player extends Base { // 设置角色数据 setAvatar (ds, source = '') { let avatar = this.getAvatar(ds.id, true) + if (!avatar.setAvatar) { + console.log(this._avatars) + console.log(avatar, ds) + } avatar.setAvatar(ds, source) } @@ -206,6 +210,7 @@ export default class Player extends Base { id = avatars['10000005'] ? 10000005 : 10000007 } } + if (!avatars[id]) { if (create) { avatars[id] = Avatar.create({ id }, this.game) @@ -213,16 +218,14 @@ export default class Player extends Base { return false } } + let avatar = avatars[id] if (!avatar.isAvatar) { let data = avatars[id] avatar = avatars[id] = Avatar.create(avatars[id], this.game) avatar.setAvatar(data) } - if (avatar.hasData) { - return avatar - } - return false + return avatar } // 循环Avatar @@ -321,6 +324,17 @@ export default class Player extends Base { return await MysAvatar.refreshTalent(this, ids, force) } + /** + * 刷新角色数据 + * + * @param cfg + * @param cfg.detail mys-detail数据更新级别,角色列表与详情 + * @param cfg.talent mys-talent数据更新级别,角色天赋数据 + * @param cfg.index mys-index数据更新级别,游戏统计数据 + * @param cfg.profile 刷新面板数据 + * @param cfg.ids 刷新的角色列表 + */ + async refresh (cfg) { this.save(false) try { @@ -331,7 +345,7 @@ export default class Player extends Base { await this.refreshMysDetail(cfg.detail) } if (cfg.talent || cfg.talent === 0) { - await this.refreshTalent(cfg.ids, cfg.talent) + await this.refreshTalent(cfg.ids || '', cfg.talent) } if (cfg.profile || cfg.profile === 0) { await this.refreshProfile(cfg.profile) @@ -343,6 +357,18 @@ export default class Player extends Base { this.save(true) } + /** + * 刷新并获取角色数据 + * + * @param cfg + * @param cfg.detail mys-detail数据更新级别,角色列表与详情 + * @param cfg.talent mys-talent数据更新级别,角色天赋数据 + * @param cfg.index mys-index数据更新级别,游戏统计数据 + * @param cfg.retType 返回类型,默认id为key对象,设置为array时返回数组 + * @param cfg.rank 返回为数组时,数据是否排序,排序规则:等级、星级、天赋、命座、武器、好感的顺序排序 + * @returns {Promise} + */ + async refreshAndGetAvatarData (cfg) { await this.refresh(cfg) @@ -360,8 +386,9 @@ export default class Player extends Base { avatarRet[ds.id] = ds let profile = avatar.getProfile() - if (profile) { - let mark = profile.getArtisMark(false) + if (avatar.isProfile) { + ds.artisSet = avatar.artis.getSetData() + let mark = avatar.getArtisMark(false) ds.artisMark = Data.getData(mark, 'mark,markClass,names') if (rank) { rank.getRank(profile) diff --git a/models/artis/Artis.js b/models/artis/Artis.js index 8a2b7f03..a377caa8 100644 --- a/models/artis/Artis.js +++ b/models/artis/Artis.js @@ -2,33 +2,137 @@ * 面板圣遗物 */ import lodash from 'lodash' -import { Artifact, ArtifactSet, Character } from '#miao.models' +import { Artifact, ArtifactSet } from '#miao.models' import { Data, Format } from '#miao' -import ArtisMark from './ArtisMark.js' -import { attrMap as attrMapGS } from '../../resources/meta/artifact/index.js' -import { attrMap as attrMapSR } from '../../resources/meta-sr/artifact/index.js' -import ArtisMarkCfg from './ArtisMarkCfg.js' -import ArtisBase from './ArtisBase.js' +import Base from '../Base.js' import ArtisAttr from './ArtisAttr.js' +import ArtisSet from './ArtisSet.js' +import ArtisMark from './ArtisMark.js' -export default class Artis extends ArtisBase { +export default class Artis extends Base { constructor (game = 'gs', isProfile = false) { - super(game) + super() + this.game = game + this.artis = {} this.isProfile = !!isProfile } + + // 获取圣遗物套装数据 + getSetData () { + return ArtisSet.getSetData(this) + } + + get sets () { + return this.getSetData().sets || {} + } + + get names () { + return this.getSetData().names || [] + } + + // 有圣遗物数据 + get hasArtis () { + return !lodash.isEmpty(this.artis) + } + + _get (key) { + let artis = this.artis + switch (key) { + case 'length': + return lodash.keys(artis).length + } + if (artis[key]) { + return artis[key] + } + } + + forEach (fn) { + lodash.forEach(this.artis, (ds, idx) => { + if (ds.name) { + return fn(ds, idx) + } + }) + } + + eachIdx (fn) { + for (let idx = 1; idx <= (this.isGs ? 5 : 6); idx++) { + this.artis[idx] = this.artis[idx] || {} + let ret = fn(this.artis[idx], idx) + if (ret === false) { + break + } + } + } + + setArtisData (ds = {}) { + this.eachIdx((arti, idx) => { + this.setArtis(idx, ds[idx] || ds[`arti${idx}`] || {}) + }) + } + + getDetail () { + let ret = {} + for (let idx = 1; idx <= 5; idx++) { + let ds = this.artis[idx] + if (ds && (ds.name || ds.id)) { + let artis = Artifact.get(ds) + if (!artis) { + continue + } + let tmp = { + ...artis?.getData('img,name,set'), + level: ds.level || 1 + } + if (ds.main && ds.attrs) { + tmp.main = ds.main || null + tmp.attrs = [] + for (let attrIdx in ds.attrs || []) { + if (ds.attrs[attrIdx]) { + tmp.attrs.push(ArtisMark.formatAttr(ds.attrs[attrIdx])) + } + } + } + ret[idx] = tmp + } + } + return ret + } + + eachArtisSet (fn) { + ArtifactSet.eachSet(this.sets, fn, this.game) + } + // 有圣遗物词条 get hasAttr () { return ArtisAttr.hasAttr(this) } - getMarkDetail (profile, withDetail = true) { - return ArtisMark.getMarkDetail(profile, withDetail) + setArtisBase (idx = 1, ds = {}) { + this.artis[idx] = this.artis[idx] || {} + let arti = this.artis[idx] + + if (this.isSr) { + let artiObj = Artifact.get(ds.id, this.game) + if (!artiObj) { + return false + } + arti.id = artiObj.id || ds.id || arti.id || '' + arti.name = artiObj.name || arti.name || '' + arti.set = artiObj.setName || arti.set || '' + arti.level = ds.level || arti.level || 1 + arti.star = artiObj.getStarById(ds.id) || arti.star || 5 + } else { + arti.name = ds.name || arti.name || '' + arti.set = ds.set || Artifact.getSetNameByArti(arti.name) || '' + arti.level = ds.level || 1 + arti.star = ds.star || 5 + } } setArtis (idx = 1, ds = {}) { idx = idx.toString().replace('arti', '') * 1 || 1 - super.setArtis(idx, ds) + this.setArtisBase(idx, ds) if (!this.isProfile) { return } @@ -55,14 +159,24 @@ export default class Artis extends ArtisBase { toJSON () { let ret = {} this.eachIdx((ds, idx) => { - let tmp = this.isGs ? { name: ds.name } : { id: ds.id } - tmp.level = ds.level || 1 - tmp.star = ds.star || 5 - ret[idx] = tmp - // 如果不为面板数据,则不保存mainId和attrIds - if (!this.isProfile) { + let key = this.isGs ? 'name' : 'id' + let tmp = { + level: ds.level || 1, + star: ds.star || 5 + } + if (!ds[key]) { return true } + tmp[key] = ds[key] + // 如果不为面板数据,则不保存mainId和attrIds + if (!this.isProfile) { + ret[idx] = tmp + return true + } + if (!ds.mainId || !ds.attrIds) { + return true + } + ret[idx] = tmp tmp.mainId = ds.mainId || ds.main?.id if (this.isSr) { tmp.attrIds = [] @@ -126,7 +240,7 @@ export default class Artis extends ArtisBase { let k = (ds) => [ds?.name || '', ds?.level || '', ds?.star || ''].join('|') let ret = true this.eachIdx((ds, idx) => { - if (k[ds] !== k(target[idx])) { + if (k(ds) !== k(target[idx])) { return ret = false } }) diff --git a/models/artis/ArtisBase.js b/models/artis/ArtisBase.js deleted file mode 100644 index f4650ec2..00000000 --- a/models/artis/ArtisBase.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * 面板圣遗物 - */ -import lodash from 'lodash' -import Base from '../Base.js' -import { Artifact, ArtifactSet } from '#miao.models' -import ArtisMark from './ArtisMark.js' -import ArtisSet from './ArtisSet.js' - -export default class ArtisBase extends Base { - constructor (game = 'gs') { - super() - this.game = game - this.artis = {} - } - - // 获取圣遗物套装数据 - getSetData () { - return ArtisSet.getSetData(this) - } - - get sets () { - return this.getSetData().sets || {} - } - - get names () { - return this.getSetData().names || [] - } - - // 有圣遗物数据 - get hasArtis () { - return !lodash.isEmpty(this.artis) - } - - _get (key) { - let artis = this.artis - switch (key) { - case 'length': - return lodash.keys(artis).length - } - if (artis[key]) { - return artis[key] - } - } - - forEach (fn) { - lodash.forEach(this.artis, (ds, idx) => { - if (ds.name) { - return fn(ds, idx) - } - }) - } - - eachIdx (fn) { - for (let idx = 1; idx <= (this.isGs ? 5 : 6); idx++) { - this.artis[idx] = this.artis[idx] || {} - let ret = fn(this.artis[idx], idx) - if (ret === false) { - break - } - } - } - - setArtisData (ds = {}) { - this.eachIdx((arti, idx) => { - this.setArtis(idx, ds[idx] || ds[`arti${idx}`] || {}) - }) - } - - setArtis (idx = 1, ds = {}) { - this.artis[idx] = this.artis[idx] || {} - let arti = this.artis[idx] - - if (this.isSr) { - let artiObj = Artifact.get(ds.id, this.game) - if (!artiObj) { - return false - } - arti.id = artiObj.id || ds.id || arti.id || '' - arti.name = artiObj.name || arti.name || '' - arti.set = artiObj.setName || arti.set || '' - arti.level = ds.level || arti.level || 1 - arti.star = artiObj.getStarById(ds.id) || arti.star || 5 - } else { - arti.name = ds.name || arti.name || '' - arti.set = ds.set || Artifact.getSetNameByArti(arti.name) || '' - arti.level = ds.level || 1 - arti.star = ds.star || 5 - } - } - - getDetail () { - let ret = {} - for (let idx = 1; idx <= 5; idx++) { - let ds = this.artis[idx] - if (ds) { - let artis = Artifact.get(ds.name) - let tmp = { - ...artis?.getData('img,name,set'), - level: ds.level || 1 - } - if (ds.main && ds.attrs) { - tmp.main = ds.main || null - tmp.attrs = [] - for (let attrIdx in ds.attrs || []) { - if (ds.attrs[attrIdx]) { - tmp.attrs.push(ArtisMark.formatAttr(ds.attrs[attrIdx])) - } - } - } - ret[idx] = tmp - } - } - return ret - } - - eachArtisSet (fn) { - ArtifactSet.eachSet(this.sets, fn, this.game) - } -} diff --git a/models/avatar/AvatarBase.js b/models/avatar/AvatarBase.js deleted file mode 100644 index a1051012..00000000 --- a/models/avatar/AvatarBase.js +++ /dev/null @@ -1,276 +0,0 @@ -import lodash from 'lodash' -import Base from '../Base.js' -import moment from 'moment' -import { Character, Avatar, Weapon } from '#miao.models' -import { Data, Format } from '#miao' -import Attr from '../attr/Attr.js' -import Artis from '../artis/Artis.js' - -const charKey = 'name,abbr,sName,star,imgs,face,side,gacha,weaponTypeName'.split(',') - -export default class AvatarBase extends Base { - constructor (ds = {}, game = 'gs') { - super() - let char = Character.get({ id: ds.id, elem: ds.elem }) - if (!char) { - return - } - this.id = char.id - this.char = char - this.game = char.game || game - this._mysArtis = new Artis(this.game) - } - - get hasTalent () { - return this.talent && !lodash.isEmpty(this.talent) && !!this._talent - } - - get name () { - return this.char?.name || '' - } - - get costume () { - let costume = this._costume - if (lodash.isArray(costume)) { - costume = costume[0] - } - return costume - } - - get originalTalent () { - return lodash.mapValues(this.talent, (ds) => ds.original) - } - - // 已经到达当前等级的最大天赋 - get isMaxTalent () { - let maxLv = [1, 2, 4, 6, 8, 10]?.[this.promote - 1] || 10 - let minTalent = lodash.min(lodash.map(this.talent, (ds) => ds.original)) - return minTalent >= maxLv - } - - get artis () { - return this._mysArtis - } - - get mysArtis () { - return this._mysArtis - } - - /** - * 获取圣遗物套装属性 - * @returns {boolean|*|{imgs: *[], names: *[], sets: {}, abbrs: *[], sName: string, name: (string|*)}|{}} - */ - get artisSet () { - return this.artis.getSetData() - } - - get dataSource () { - return { - enka: 'Enka.Network', - miao: '喵喵Api', - mgg: 'MiniGG-Api', - hutao: 'Hutao-Enka', - mys: '米游社', - homo: 'Mihomo' - }[this._source] || this._source - } - - get updateTime () { - let time = this._time - if (!time) { - return '' - } - if (lodash.isString(time)) { - return moment(time).format('MM-DD HH:mm') - } - if (lodash.isNumber(time)) { - return moment(new Date(time)).format('MM-DD HH:mm') - } - return '' - } - - static create (ds, game = 'gs') { - let avatar = new AvatarBase(ds, game) - if (!avatar) { - return false - } - return avatar - } - - _get (key) { - if (charKey.includes(key)) { - return this.char[key] - } - } - - setAvatar (ds, source = '') { - this._now = new Date() * 1 - this.setBasic(ds, source) - ds.weapon && this.setWeapon(ds.weapon) - ds.talent && this.setTalent(ds.talent, 'original', source) - let artis = ds.mysArtis || ds.artis - // 只要具备圣遗物信息,就更新mysArtis - this._mysArtis.setArtisData(artis) - delete this._now - } - - /** - * 设置角色基础数据 - * @param ds - * @param source - */ - setBasic (ds = {}, source = '') { - const now = this._now || (new Date()) * 1 - this.level = ds.lv || ds.level || this.level || 1 - this.cons = ds.cons || this.cons || 0 - this.fetter = ds.fetter || this.fetter || 0 - this._costume = ds.costume || this._costume || 0 - this.elem = ds.elem || this.elem || this.char.elem || '' - this.promote = lodash.isUndefined(ds.promote) ? (this.promote || Attr.calcPromote(this.level)) : (ds.promote || 0) - this.trees = this.trees || [] - this._source = ds._source || this._source || '' // 数据源 - this._time = ds._time || this._time || now // 面板最后更新时间 - this._update = ds._update || this._update || ds._time || now //最后更新时间,包括mys - this._talent = ds._talent || this._talent || ds._time || now // 最后天赋更新时间,包括mys - - if (ds.trees) { - this.setTrees(ds.trees) - } - - // 存在数据源时更新时间 - if (source) { - this._update = now - if (source !== 'mys') { - this._source = source - this._time = now - } else { - this._source = this._source || source - this._time = this._source !== 'mys' ? (this._time || now) : now - } - } - } - - // 星铁的行迹数据 - setTrees (ds) { - this.trees = [] - let prefix = '' - let map = {} - lodash.forEach(this.char?.detail?.tree || {}, (ds, key) => { - let ret = /(\d{4})(\d{3})/.exec(key) - if (ret && ret[1] && ret[2]) { - prefix = prefix || ret[1] - map[ret[2]] = key - } - }) - if (prefix) { - for (let i = 0; i <= 3; i++) { - map[`10${i}`] = `${prefix}10${i}` - } - } - lodash.forEach(ds, (id) => { - let ret = /\d{4}(\d{3})/.exec(id) - this.trees.push(map[ret?.[1] || id] || id) - }) - } - - // 设置武器 - setWeapon (ds = {}) { - let w = Weapon.get(ds.name || ds.id, this.game) - if (!w) { - return false - } - this.weapon = { - id: ds.id || w.id, - name: ds.name || w.name, - level: ds.level || ds.lv || 1, - promote: lodash.isUndefined(ds.promote) ? Attr.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0), - affix: ds.affix, - ...w.getData('star,abbr,type,img') - } - if (this.weapon.level < 20) { - this.weapon.promote = 0 - } - } - - // 获取武器详情信息 - getWeaponDetail () { - let ret = { - ...this.weapon - } - if (!ret.id) { - return {} - } - let wData = Weapon.get(ret.id, this.game) - ret.splash = wData.imgs.gacha - let wAttr = wData.calcAttr(ret.level, ret.promote) - let attrs = {} - if (this.isSr) { - lodash.forEach(wAttr, (val, key) => { - attrs[key] = Format.comma(val, 1) - }) - } else if (this.isGs) { - attrs.atkBase = Format.comma(wAttr.atkBase, 1) - if (wAttr?.attr?.key) { - let keyType = { - mastery: 'comma' - } - attrs[wAttr.attr.key] = Format[keyType[wAttr.attr.key] || 'pct'](wAttr.attr.value, 1) - } - } - ret.attrs = attrs - ret.desc = wData.getAffixDesc(ret.affix) - return ret - } - - // 设置天赋 - setTalent (ds = false, mode = 'original', updateTime = '') { - const now = this._now || (new Date()) * 1 - if (ds) { - let ret = this.char.getAvatarTalent(ds, this.cons, mode) - if (ret) { - this.talent = ret || this.talent - // 设置天赋更新时间 - this._talent = ds._talent || this._talent || ds._time || now - } - } - if (updateTime) { - this._talent = now - } - } - - setArtis (ds) { - this.mysArtis.setArtisData(ds.mysArtis || ds.artis) - } - - getProfile () { - if (!this.isProfile) { - return false - } - return Avatar.create(this, this.game) - } - - // 判断当前profileData是否具备有效圣遗物信息 - hasArtis () { - return this.isProfile && this.artis.length > 0 - } - - // 获取数据详情 - getDetail (keys = '') { - let imgs = this.char.getImgs(this.costume) - if (this.isGs) { - return { - ...(this.getData(keys || 'id,name,level,star,cons,fetter,elem,abbr,weapon,talent,artisSet') || {}), - ...Data.getData(imgs, 'face,qFace,side,gacha') - } - } else { - return { - ...(this.getData(keys || 'id,name,level,star,cons,elem,abbr,weapon,talent,artisSet,trees') || {}), - ...Data.getData(imgs, 'face,qFace,gacha,preview') - } - } - } - - getArtisDetail () { - return this.artis.getDetail() - } -} diff --git a/models/avatar/MysAvatar.js b/models/avatar/MysAvatar.js index 754c76a1..976d13f7 100644 --- a/models/avatar/MysAvatar.js +++ b/models/avatar/MysAvatar.js @@ -5,6 +5,7 @@ import { chestInfo } from '../../resources/meta/info/index.js' import AvatarUtil from './AvatarUtil.js' const MysAvatar = { + // 检查更新force值 checkForce (player, force) { let e = player?.e let mys = e?._mys @@ -15,6 +16,8 @@ const MysAvatar = { if (!ck || player._ck === ck) { return force } + return force + // 暂时不处理ck变更 player._info = 0 player._mys = 0 player.forEachAvatar((avatar) => { @@ -209,10 +212,10 @@ const MysAvatar = { // 并发5,请求天赋数据 await Data.asyncPool(5, needReqIds, async (id) => { let avatar = player.getAvatar(id) - if (!avatar || avatar.isMaxTalent) { + if (avatar) { return false } - if (failCount > 5) { + if (avatar.isMaxTalent || failCount > 5) { avatar.setTalent(false, 'original', true) return false }