* #雷神面板 属性部分样式调整,增加圣遗物评分权重展示

* 圣遗物评级的分数上限微调
This commit is contained in:
Kokomi 2023-03-05 15:21:44 +08:00
parent f4ed430ec7
commit 244b1f5c66
16 changed files with 294 additions and 116 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@
/config/cfg.js /config/cfg.js
/resources/profile/super-character/* /resources/profile/super-character/*
/resources/profile/normal-character/* /resources/profile/normal-character/*
/node_modules/

View File

@ -1,8 +1,9 @@
# 2.3.4 # 2.3.5
* 增加白术、卡维的角色信息,可通过`#白术天赋`、`#白术图鉴`等查看 * `#雷神面板` 属性部分样式调整,增加圣遗物评分权重展示
* 圣遗物评级的分数上限微调
# 2.3.1~2.3.3 # 2.3.1~2.3.4
* 增加`#角色记录``#抽卡统计`功能,可在`#喵喵设置`中开启 * 增加`#角色记录``#抽卡统计`功能,可在`#喵喵设置`中开启
* `#角色记录`、`#武器记录`、`#常驻记录` 可查看对应池子的抽卡记录 * `#角色记录`、`#武器记录`、`#常驻记录` 可查看对应池子的抽卡记录
@ -17,6 +18,7 @@
* 使用statsIds存储圣遗物数据能够更精确的计算角色属性 * 使用statsIds存储圣遗物数据能够更精确的计算角色属性
* `#喵喵设置`中可区分国服、B服、外服分别设置面板服务器具体参见喵喵设置 * `#喵喵设置`中可区分国服、B服、外服分别设置面板服务器具体参见喵喵设置
* `#面板`、`#角色`等页面使用Q版头像(@QuAn_、Misaaa),可在#喵喵设置 中关闭 * `#面板`、`#角色`等页面使用Q版头像(@QuAn_、Misaaa),可在#喵喵设置 中关闭
* 增加白术、卡维的角色信息,可通过`#白术天赋`、`#白术图鉴`等查看
* 部分已知问题调整或优化 * 部分已知问题调整或优化
* 圣遗物、天赋更新策略及更新逻辑优化 * 圣遗物、天赋更新策略及更新逻辑优化
* 面板更新的提醒文案逻辑优化 * 面板更新的提醒文案逻辑优化

View File

@ -125,22 +125,31 @@ let ProfileDetail = {
} }
char = profile.char || char char = profile.char || char
let a = profile.attr let a = profile.attr
let base = profile.base
let c = Format.comma let c = Format.comma
let p = Format.pct let p = Format.pct
let attr = { let attr = {}
hp: c(a.hp), lodash.forEach(['hp', 'def', 'atk', 'mastery'], (key) => {
hpPlus: c(a.hp - a.hpBase), attr[key] = c(a[key])
atk: c(a.atk), attr[`${key}Base`] = c(base[key])
atkPlus: c(a.atk - a.atkBase), attr[`${key}Plus`] = c(a[key] - base[key])
def: c(a.def), })
defPlus: c(a.def - a.defBase), lodash.forEach(['cpct', 'cdmg', 'recharge'], (key) => {
cpct: p(a.cpct), attr[key] = p(a[key])
cdmg: p(a.cdmg), attr[`${key}Base`] = p(base[key])
mastery: c(a.mastery), attr[`${key}Plus`] = p(a[key] - base[key])
recharge: p(a.recharge), })
dmg: p(Math.max(a.dmg * 1 || 0, a.phy * 1 || 0)) if (a.dmg > a.phy) {
attr.dmg = p(a.dmg * 1 || 0)
attr.dmgBase = p(base.dmg * 1 || 0)
attr.dmgPlus = p((a.dmg * 1 || 0) - (base.dmg * 1 || 0))
} else {
attr.dmg = p(a.phy * 1 || 0)
attr.dmgBase = p(base.phy * 1 || 0)
attr.dmgPlus = p((a.phy * 1 || 0) - (base.phy * 1 || 0))
} }
let weapon = Weapon.get(profile.weapon.name) let weapon = Weapon.get(profile.weapon.name)
let w = profile.weapon let w = profile.weapon
let wCfg = {} let wCfg = {}

View File

@ -10,26 +10,29 @@ class ProfileAttr extends Base {
this.init(data) this.init(data)
} }
static create (data = null) {
return new ProfileAttr(data)
}
init (data) { init (data) {
// 基础属性 // 基础属性
this._attr = {} this._attr = {}
this._base = {}
let attr = this._attr let attr = this._attr
let base = this._base
lodash.forEach(baseAttr, (key) => { lodash.forEach(baseAttr, (key) => {
attr[key] = { attr[key] = {
base: 0, base: 0,
plus: 0, plus: 0,
pct: 0 pct: 0
} }
base[key] = 0
}) })
if (data) { if (data) {
this.setAttr(data, true) this.setAttr(data, true)
} }
} }
static create (data = null) {
return new ProfileAttr(data)
}
/** /**
* getter * getter
* *
@ -56,12 +59,17 @@ class ProfileAttr extends Base {
* 添加或追加Attr数据 * 添加或追加Attr数据
* @param key * @param key
* @param val * @param val
* @param base
* @returns {boolean} * @returns {boolean}
*/ */
addAttr (key, val) { addAttr (key, val, isBase = false) {
let attr = this._attr let attr = this._attr
let base = this._base
if (baseAttr.includes(key)) { if (baseAttr.includes(key)) {
attr[key].plus += val * 1 attr[key].plus += val * 1
if (isBase) {
base[key] = (base[key] || 0) + val * 1
}
return true return true
} }
@ -71,6 +79,9 @@ class ProfileAttr extends Base {
let key2 = testRet[2].toLowerCase() let key2 = testRet[2].toLowerCase()
attr[key][key2] = attr[key][key2] || 0 attr[key][key2] = attr[key][key2] || 0
attr[key][key2] += val * 1 attr[key][key2] += val * 1
if (key2 === 'base' || isBase) {
base[key] = (base[key] || 0) + val * 1
}
return true return true
} }
return false return false
@ -107,6 +118,10 @@ class ProfileAttr extends Base {
ret._calc = true ret._calc = true
return ret return ret
} }
getBase () {
return this._base
}
} }
export default ProfileAttr export default ProfileAttr

View File

@ -78,6 +78,7 @@ export default class ProfileData extends AvatarData {
calcAttr () { calcAttr () {
this._attr = AttrCalc.create(this) this._attr = AttrCalc.create(this)
this.attr = this._attr.calc() this.attr = this._attr.calc()
this.base = this._attr.getBase()
} }
setArtis (ds = false) { setArtis (ds = false) {

View File

@ -161,7 +161,7 @@ let ArtisMark = {
// 获取评分档位 // 获取评分档位
getMarkClass (mark) { getMarkClass (mark) {
let pct = 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.1]] let scoreMap = [['D', 7], ['C', 14], ['B', 21], ['A', 28], ['S', 35], ['SS', 42], ['SSS', 49], ['ACE', 56], ['ACE²', 66.1]]
for (let idx = 0; idx < scoreMap.length; idx++) { for (let idx = 0; idx < scoreMap.length; idx++) {
if (pct < scoreMap[idx][1]) { if (pct < scoreMap[idx][1]) {
return scoreMap[idx][0] return scoreMap[idx][0]

View File

@ -47,19 +47,23 @@ class AttrCalc {
* @returns {{}} * @returns {{}}
*/ */
calc () { calc () {
this.attr = ProfileAttr.create({ this.attr = ProfileAttr.create({})
recharge: 100, this.addAttr('recharge', 100, true)
cpct: 5, this.addAttr('cpct', 5, true)
cdmg: 50 this.addAttr('cdmg', 50, true)
})
this.setCharAttr() this.setCharAttr()
this.setWeaponAttr() this.setWeaponAttr()
this.setArtisAttr() this.setArtisAttr()
return this.attr.getAttr() return this.attr.getAttr()
} }
addAttr (key, val) { getBase () {
this.attr.addAttr(key, val) return this.attr.getBase()
}
addAttr (key, val, isBase = false) {
this.attr.addAttr(key, val, isBase)
} }
/** /**
@ -96,10 +100,10 @@ class AttrCalc {
return valueLeft * 1 + ((valueRight - valueLeft) * Math.floor((level - lvLeft) / 5) / Math.round(((lvRight - lvLeft) / 5))) return valueLeft * 1 + ((valueRight - valueLeft) * Math.floor((level - lvLeft) / 5) / Math.round(((lvRight - lvLeft) / 5)))
} }
} }
this.addAttr('hpBase', getLvData(0)) this.addAttr('hpBase', getLvData(0), true)
this.addAttr('atkBase', getLvData(1)) this.addAttr('atkBase', getLvData(1), true)
this.addAttr('defBase', getLvData(2)) this.addAttr('defBase', getLvData(2), true)
this.addAttr(keys[3], getLvData(3, true)) this.addAttr(keys[3], getLvData(3, true), true)
let charBuffs = char.getCalcRule() let charBuffs = char.getCalcRule()
lodash.forEach(charBuffs.buffs, (buff) => { lodash.forEach(charBuffs.buffs, (buff) => {

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "miao-plugin",
"version": "2.3.3",
"author": "Yoimiya-Kokomi",
"description": "miao-plugin",
"type": "module",
"scripts": {
},
"dependencies": {
"image-size": "^1.0.2"
},
"peerDependencies": {
"image-size": "^1.0.2"
},
"devDependencies": {
},
"pnpm": {
"patchedDependencies": {}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

View File

@ -197,8 +197,7 @@
<li><strong>最优主词缀比例: </strong>对主词条词缀非最优的圣遗物进行评分惩罚。若装备的圣遗物主词条不是当前位置的最高权重主词条或元素杯属性不符则依据权重差值比例进行分数扣减最多扣减50%。主词缀为充能时不进行扣减 <li><strong>最优主词缀比例: </strong>对主词条词缀非最优的圣遗物进行评分惩罚。若装备的圣遗物主词条不是当前位置的最高权重主词条或元素杯属性不符则依据权重差值比例进行分数扣减最多扣减50%。主词缀为充能时不进行扣减
</li> </li>
<li><strong>最终得分:</strong>圣遗物最终得分 = 原始总分 * 总分对齐比例 * 最优主词缀比例</li> <li><strong>最终得分:</strong>圣遗物最终得分 = 原始总分 * 总分对齐比例 * 最优主词缀比例</li>
<li><strong>得分级别:</strong>ACE²(&gt;56.1分) / ACE(&gt;49.5分) / SSS(&gt;42.9分) / SS(&gt;36.3分) / S(&gt;29.7分) / A / B / <li><strong>得分级别:</strong>ACE²(&gt;56分) / ACE(&gt;49分) / SSS(&gt;42分) / SS(&gt;35分) / S(&gt;28分) / A / B / C / D
C / D
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -61,68 +61,116 @@ body {
margin-left: 5px; margin-left: 5px;
vertical-align: bottom; vertical-align: bottom;
} }
.attr { .char-attr {
border-radius: 4px; backdrop-filter: blur(2px);
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
overflow: hidden; overflow: hidden;
} }
.detail ul.attr { .char-attr li {
background: rgba(0, 0, 0, 0.2);
}
.detail ul.attr li {
width: 300px; width: 300px;
font-size: 17px; font-size: 17px;
list-style: none; list-style: none;
padding: 0 100px 0 35px;
position: relative;
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
text-shadow: 0 0 1px rgba(0, 0, 0, 0.5); text-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
display: flex;
padding-left: 3px;
} }
.detail ul.attr li i { .char-attr li:nth-child(even) {
background: rgba(0, 0, 0, 0.4);
}
.char-attr li:nth-child(odd) {
background: rgba(50, 50, 50, 0.4);
}
.char-attr li .weight {
width: 36px;
}
.char-attr li .weight span {
display: block;
width: 30px;
border-radius: 5px;
font-size: 12px;
height: 18px;
line-height: 18px;
background: rgba(0, 0, 0, 0.5);
text-align: center;
margin: 7px auto 0;
}
.char-attr li .weight span.gold {
color: #ffe699;
}
.char-attr li .icon {
width: 26px;
padding: 2px 5px;
}
.char-attr li .icon i {
display: inline-block; display: inline-block;
height: 20px; height: 16px;
width: 20px; width: 16px;
background-image: url("./imgs/icon.png"); background-image: url("./imgs/icon.png");
background-size: auto 20px; background-size: auto 16px;
position: absolute; }
left: 10px; .char-attr li .title {
top: 8px; width: 75px;
opacity: 0.9; }
transform: scale(0.9); .char-attr li .value {
width: 110px;
text-align: right;
font-weight: normal;
padding-right: 10px;
}
.char-attr li .value2 {
font-weight: normal;
width: 60px;
text-align: right;
font-size: 12px;
padding: 4px 10px 0 0;
background: rgba(0, 0, 0, 0.2);
}
.char-attr li .value2 span {
display: block;
height: 13px;
line-height: 13px;
transform: scale(0.85);
transform-origin: right center;
}
.char-attr li .value2 .base {
color: #eee;
}
.char-attr li .value2 .plus {
color: #90e800;
} }
.i-hp { .i-hp {
background-position: -20px 0; background-position: -16px 0;
} }
.i-atk { .i-atk {
background-position: -40px 0; background-position: -32px 0;
} }
.i-def { .i-def {
background-position: -60px 0; background-position: -48px 0;
} }
.i-mastery { .i-mastery {
background-position: -64px 0;
}
.i-cpct {
background-position: -80px 0; background-position: -80px 0;
} }
.i-cr { .i-cdmg {
background-position: -100px 0; background-position: -96px 0;
} }
.i-cd { .i-recharge {
background-position: -140px 0; background-position: -112px 0;
}
.i-re {
background-position: -120px 0;
} }
.i-dmg { .i-dmg {
background-position: -160px 0; background-position: -128px 0;
} }
.detail .attr li:nth-child(even),
.detail.attr li:nth-child(even) { .detail.attr li:nth-child(even) {
background: rgba(0, 0, 0, 0.4); background: rgba(0, 0, 0, 0.4);
} }
.detail .attr li:nth-child(odd),
.detail.attr li:nth-child(odd) { .detail.attr li:nth-child(odd) {
background: rgba(50, 50, 50, 0.4); background: rgba(50, 50, 50, 0.4);
} }
.detail .attr li strong,
.detail.attr li strong { .detail.attr li strong {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
@ -130,7 +178,6 @@ body {
text-align: right; text-align: right;
font-weight: normal; font-weight: normal;
} }
.detail .attr li span,
.detail.attr li span { .detail.attr li span {
position: absolute; position: absolute;
right: 0; right: 0;

View File

@ -35,15 +35,30 @@
</div> </div>
{{/each}} {{/each}}
</div> </div>
<ul class="attr"> <ul class="char-attr">
<li><i class="i-hp"></i>生命值<strong>{{attr.hp}}</strong><span>(+{{attr.hpPlus}})</span></li> {{set attrMap = {hp:'生命值',atk:'攻击力',def:'防御力',mastery:'元素精通',cpct:'暴击率',cdmg:'暴击伤害',recharge:'元素充能',dmg:'伤害加成'} }}
<li><i class="i-atk"></i>攻击力<strong>{{attr.atk}}</strong><span>(+{{attr.atkPlus}})</span></li> {{set cw = artisDetail?.charWeight || {} }}
<li><i class="i-def"></i>防御力<strong>{{attr.def}}</strong><span>(+{{attr.defPlus}})</span></li> {{each attrMap title key}}
<li><i class="i-mastery"></i>元素精通<strong>{{attr.mastery}}</strong></li> <li>
<li><i class="i-cr"></i>暴击率<strong>{{attr.cpct}}</strong></li>
<li><i class="i-cd"></i>暴击伤害<strong>{{attr.cdmg}}</strong></li> <div class="icon"><i class="i-{{key}}"></i></div>
<li><i class="i-re"></i>元素充能<strong>{{attr.recharge}}</strong></li>
<li><i class="i-dmg"></i>伤害加成<strong>{{attr.dmg}}</strong></li> <div class="title">{{title}}</div>
<div class="weight">
{{if cw[key]}}
<span class="{{cw[key]>=80?'gold':'normal'}}">{{cw[key]}}</span>
{{/if}}
</div>
<div class="value">
{{attr[key]}}
</div>
<div class="value2">
<span class="base"><i>+</i>{{attr[key+'Base']}}</span>
<span class="plus">+{{attr[key+'Plus']}}</span>
</div>
</li>
{{/each}}
</ul> </ul>
{{else}} {{else}}
<div class="char-weapon"> <div class="char-weapon">

View File

@ -67,74 +67,139 @@ body {
} }
} }
.attr { @i: 16px;
border-radius: 4px;
overflow: hidden;
}
.detail ul.attr { .char-attr {
// backdrop-filter: blur(4px); backdrop-filter: blur(2px);
background: rgba(0, 0, 0, .2); background: rgba(0, 0, 0, .2);
border-radius: 8px;
overflow: hidden;
li { li {
width: 300px; width: 300px;
font-size: 17px; font-size: 17px;
list-style: none; list-style: none;
padding: 0 100px 0 35px;
position: relative;
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
text-shadow: 0 0 1px rgba(0, 0, 0, .5); text-shadow: 0 0 1px rgba(0, 0, 0, .5);
display: flex;
padding-left: 3px;
i { &:nth-child(even) {
display: inline-block; background: rgba(0, 0, 0, .4)
height: 20px; }
width: 20px;
background-image: url("./imgs/icon.png"); &:nth-child(odd) {
background-size: auto 20px; background: rgba(50, 50, 50, .4)
position: absolute; }
left: 10px;
top: 8px; .weight {
opacity: .9; width: 36px;
transform: scale(.9);
span {
display: block;
width: 30px;
border-radius: 5px;
font-size: 12px;
height: 18px;
line-height: 18px;
background: rgba(0, 0, 0, .5);
text-align: center;
margin: 7px auto 0;
&.gold {
color: #ffe699;
}
}
}
.icon {
width: @i+10px;
padding: 2px 5px;
i {
display: inline-block;
height: @i;
width: @i;
background-image: url("./imgs/icon.png");
background-size: auto @i;
}
}
.title {
width: 75px;
} }
.value {
width: 110px;
text-align: right;
font-weight: normal;
padding-right: 10px;
}
.value2 {
font-weight: normal;
width: 60px;
text-align: right;
font-size: 12px;
padding: 4px 10px 0 0;
background: rgba(0, 0, 0, .2);
span {
display: block;
height: 13px;
line-height: 13px;
transform: scale(.85);
transform-origin: right center;
}
.base {
color: #eee;
}
.plus {
color: #90e800;
}
}
} }
} }
.i-hp { .i-hp {
background-position: -20px 0; background-position: @i*-1 0;
} }
.i-atk { .i-atk {
background-position: -40px 0; background-position: @i*-2 0;
} }
.i-def { .i-def {
background-position: -60px 0; background-position: @i*-3 0;
} }
.i-mastery { .i-mastery {
background-position: -80px 0; background-position: @i*-4 0;
} }
.i-cr { .i-cpct {
background-position: -100px 0; background-position: @i*-5 0;
} }
.i-cd { .i-cdmg {
background-position: -140px 0; background-position: @i*-6 0;
} }
.i-re { .i-recharge {
background-position: -120px 0; background-position: @i*-7 0;
} }
.i-dmg { .i-dmg {
background-position: -160px 0; background-position: @i*-8 0;
} }
.detail .attr, .detail.attr { .detail.attr {
li { li {
&:nth-child(even) { &:nth-child(even) {
background: rgba(0, 0, 0, .4) background: rgba(0, 0, 0, .4)

View File

@ -45,14 +45,14 @@ body {
padding-left: 20px; padding-left: 20px;
} }
.detail ul.char-attr li strong { .detail ul.char-attr li strong {
position: initial;
color: #d3bc8e; color: #d3bc8e;
width: 85px;
font-weight: normal;
} }
.detail ul.char-attr li span { .detail ul.char-attr li span {
color: #fff; color: #fff;
right: 20px;
text-align: right; text-align: right;
width: 150px; width: 130px;
} }
.material-list { .material-list {
display: flex; display: flex;

View File

@ -65,15 +65,15 @@ body {
padding-left: 20px; padding-left: 20px;
strong { strong {
position: initial;
color: #d3bc8e; color: #d3bc8e;
width: 85px;
font-weight: normal;
} }
span { span {
color: #fff; color: #fff;
right: 20px;
text-align: right; text-align: right;
width: 150px; width: 130px;
} }
} }
} }

View File

@ -24,7 +24,7 @@ app.use(express.static(_path + '/resources'))
app.use('/plugins', express.static('plugins')) app.use('/plugins', express.static('plugins'))
app.get('/', function (req, res) { app.get('/', function (req, res) {
let pluginList = fs.readdirSync(_path + '/data/ViewData/') || [] let pluginList = fs.readdirSync(_path + '/temp/ViewData/') || []
let html = [ let html = [
'在npm run web-dev模式下触发截图消息后可在下方选择页面进行调试', '在npm run web-dev模式下触发截图消息后可在下方选择页面进行调试',
'如果页面内资源路径不正确请使用{{_res_path}}作为根路径,对应之前的../../../../', '如果页面内资源路径不正确请使用{{_res_path}}作为根路径,对应之前的../../../../',
@ -33,7 +33,7 @@ app.get('/', function (req, res) {
let li = {} let li = {}
for (let pIdx in pluginList) { for (let pIdx in pluginList) {
const plugin = pluginList[pIdx] const plugin = pluginList[pIdx]
let fileList = fs.readdirSync(_path + `/data/ViewData/${plugin}/`) || [] let fileList = fs.readdirSync(_path + `/temp/ViewData/${plugin}/`) || []
for (let idx in fileList) { for (let idx in fileList) {
let ret = /(.+)\.json$/.exec(fileList[idx]) let ret = /(.+)\.json$/.exec(fileList[idx])
if (ret && ret[1]) { if (ret && ret[1]) {
@ -50,7 +50,7 @@ app.get('/:page', function (req, res) {
if (plugin == 'favicon.ico') { if (plugin == 'favicon.ico') {
return res.send('') return res.send('')
} }
let data = JSON.parse(fs.readFileSync(_path + `/data/ViewData/${plugin}/${app}_${page}.json`, 'utf8')) let data = JSON.parse(fs.readFileSync(_path + `/temp/ViewData/${plugin}/${app}_${page}.json`, 'utf8'))
data = data || {} data = data || {}
data._res_path = '' data._res_path = ''
data._sys_res_path = data._res_path data._sys_res_path = data._res_path