feature:角色面板新增词条统计

This commit is contained in:
UCPr 2025-03-29 02:00:05 +08:00
parent 6081513de5
commit b51cf93758
8 changed files with 267 additions and 78 deletions

View file

@ -44,28 +44,37 @@ export function idToClassName(_id) {
/**
* 获取属性标识
* @param {string | number} _id 属性id
* @param {string | number} id 属性id
* @returns {string | null}
*/
export const idToSignName = _id => {
const id = _id.toString();
export const idToSignName = id => {
const result = propertyData[id];
if (!result) return null;
return result[0];
};
/**
* 获取属性
* @param {string | number} _id 属性id
* 获取属性
* @param {string | number} id 属性id
* @returns {string | null}
*/
export const idToName = _id => {
const id = _id.toString();
export const idToName = id => {
const result = propertyData[id];
if (!result) return null;
return result[1];
};
/**
* 获取属性二字简称
* @param {string | number} id 属性id
* @returns {string | null}
*/
export const idToShortName = id => {
const result = propertyData[id];
if (!result) return null;
return result[2];
};
/**
* 属性名转id
* @param {string} propName 属性名

View file

@ -48,14 +48,7 @@ for (const charName in equipScore) {
* @returns {number}
*/
export const getEquipPropertyEnhanceCount = (propertyID, value) => {
if (value.includes('%')) {
value = value.replace('%', '');
}
value = Number(value);
propertyID = String(propertyID);
const baseValue = baseValueData[propertyID] || 0;
if (baseValue === 0) {
return 0;
}
return value / baseValue - 1;
const baseValue = baseValueData[propertyID];
value = +value.replace('%', '');
return value / baseValue - 1 || 0;
};

View file

@ -4,16 +4,16 @@ import {
getSmallSquareAvatar,
getSquareAvatar,
} from '../lib/download.js';
import { formatScoreWeight, scoreWeight } from '../lib/score.js';
import { baseValueData, formatScoreWeight, scoreWeight } from '../lib/score.js';
import { avatar_ability, scoreFnc } from './damage/avatar.js';
import { idToShortName } from '../lib/convert/property.js';
import { imageResourcesPath } from '../lib/path.js';
import { Equip, Weapon } from './equip.js';
import { Property } from './property.js';
import { Skill } from './skill.js';
import path from 'path';
import _ from 'lodash';
import fs from 'fs';
import path from 'path';
/**
* @class
@ -357,6 +357,7 @@ export class ZZZAvatarInfo {
/** @type {number|boolean} */
get equip_score() {
if (!this.equip?.length) return false;
if (this.scoreWeight) {
let score = 0;
for (const equip of this.equip) {
@ -434,6 +435,35 @@ export class ZZZAvatarInfo {
return result;
}
/** 词条统计 */
get propertyStats() {
/** @type {{ [propID: string]: { id: number, name: string, weight: number, value: string, count: number } }} */
const stats = {}
for (const equip of this.equip) {
for (const property of equip.properties) {
const propID = property.property_id
stats[propID] ??= {
id: propID,
name: idToShortName(propID),
weight: this.scoreWeight[propID] || 0,
value: '0',
count: 0
}
stats[propID].count += property.count + 1
}
}
const statsArr = Object.values(stats)
statsArr.forEach(stat => {
if (baseValueData[stat.id]) {
stat.value = (baseValueData[stat.id] * stat.count).toFixed(1)
if ([11102, 12102, 13102, 20103, 21103].includes(stat.id)) {
stat.value = `${stat.value}%`
}
}
})
return _.orderBy(statsArr, ['count', 'weight'], ['desc', 'desc'])
}
/** 面板属性label效果 */
get_label(propID) {
const base = this.scoreWeight?.[propID];

View file

@ -31,12 +31,10 @@ export class EquipProperty {
this.base = base;
this.base_score = 0
this.classname = property.idToClassName(property_id);
/** 词条强化次数 */
this.count = getEquipPropertyEnhanceCount(property_id, base);
}
/** @type {number} */
get count() {
return getEquipPropertyEnhanceCount(this.property_id, this.base);
}
}
/**

View file

@ -1,21 +1,21 @@
{
"11102": ["HPRatio", "生命值百分比"],
"11103": ["HP", "生命值"],
"12102": ["ATKRatio", "攻击力百分比"],
"12103": ["ATK", "攻击力"],
"12202": ["Impact", "冲击力"],
"13102": ["DEFRatio", "防御力百分比"],
"13103": ["DEF", "防御力"],
"20103": ["CRITRate", "暴击率"],
"21103": ["CRITDMG", "暴击伤害"],
"23103": ["PenRatio", "穿透率"],
"23203": ["Pen", "穿透值"],
"30502": ["EnergyRegen", "能量回复"],
"31203": ["AnomalyProficiency", "异常精通"],
"31403": ["AnomalyMastery", "异常掌控"],
"31503": ["PhysicalDMGBonus", "物理属性伤害提高"],
"31603": ["FireDMGBonus", "火属性伤害提高"],
"31703": ["IceDMGBonus", "冰属性伤害提高"],
"31803": ["ElectricDMGBonus", "电属性伤害提高"],
"31903": ["EtherDMGBonus", "以太属性伤害提高"]
"11102": ["HPRatio", "生命值百分比", "生命"],
"11103": ["HP", "生命值", "生命"],
"12102": ["ATKRatio", "攻击力百分比", "攻击"],
"12103": ["ATK", "攻击力", "攻击"],
"12202": ["Impact", "冲击力", "冲击"],
"13102": ["DEFRatio", "防御力百分比", "防御"],
"13103": ["DEF", "防御力", "防御"],
"20103": ["CRITRate", "暴击率", "暴击"],
"21103": ["CRITDMG", "暴击伤害", "暴伤"],
"23103": ["PenRatio", "穿透率", "穿透"],
"23203": ["Pen", "穿透值", "穿透"],
"30502": ["EnergyRegen", "能量回复", "能量"],
"31203": ["AnomalyProficiency", "异常精通", "精通"],
"31403": ["AnomalyMastery", "异常掌控", "掌控"],
"31503": ["PhysicalDMGBonus", "物理属性伤害提高", "物伤"],
"31603": ["FireDMGBonus", "火属性伤害提高", "火伤"],
"31703": ["IceDMGBonus", "冰属性伤害提高", "冰伤"],
"31803": ["ElectricDMGBonus", "电属性伤害提高", "电伤"],
"31903": ["EtherDMGBonus", "以太属性伤害提高", "以伤"]
}

View file

@ -489,14 +489,22 @@
background-clip: text;
color: transparent;
}
.card .equip-score {
.card .equip-stats {
display: flex;
padding: 0 1.8em;
height: 6em;
}
.card .equip-stats .equip-score {
border: #707070 solid;
border-width: 0.2em 0 0.2em 0.2em;
border-radius: 0.6em 0 0 0.6em;
display: flex;
justify-content: center;
font-size: 1.2em;
font-size: 1em;
align-items: center;
gap: 0.2em;
width: 30%;
}
.card .equip-score .comment-box {
.card .equip-stats .equip-score .comment-box {
font-size: 1.2em;
width: 2em;
display: flex;
@ -510,16 +518,75 @@
position: relative;
z-index: 1;
}
.card .equip-score .value {
.card .equip-stats .equip-score .value {
border: 0.1em solid rgb(155, 155, 155);
border-left: none;
padding: 0.1em 1em 0.1em 1em;
margin-left: -0.6em;
border-radius: 0 1em 1em 0;
}
.card .equip-score .value .subt {
.card .equip-stats .equip-score .value .subt {
font-size: 0.8em;
}
.card .equip-stats .property-stats {
width: 70%;
height: 100%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
font-size: 0.8em;
align-items: center;
border: #707070 solid;
border-width: 0.2em;
border-radius: 0 0.6em 0.6em 0;
overflow: hidden;
}
.card .equip-stats .property-stats .stat-item {
width: 33.33%;
height: 33.33%;
padding: 0 0.2em;
position: relative;
display: flex;
align-items: center;
white-space: nowrap;
color: #eee;
border: #707070 0.1em solid;
}
.card .equip-stats .property-stats .stat-item:nth-child(7) {
border-radius: 0 0.4em 0 0;
}
.card .equip-stats .property-stats .stat-item:nth-child(9) {
border-radius: 0 0 0.4em 0;
}
.card .equip-stats .property-stats .stat-item.great {
color: rgb(249, 189, 64);
}
.card .equip-stats .property-stats .stat-item.good {
color: rgb(238, 207, 139);
}
.card .equip-stats .property-stats .stat-item.useless {
color: #999999;
}
.card .equip-stats .property-stats .stat-item span.title {
padding-left: 0.1em;
text-align: left;
width: 48%;
}
.card .equip-stats .property-stats .stat-item span.title span.count {
display: inline-block;
text-align: center;
background-color: black;
width: 1.6em;
height: 1.6em;
border: #696969 0.15em solid;
border-radius: 0.4em;
}
.card .equip-stats .property-stats .stat-item span.value {
padding-right: 0.2em;
width: 52%;
overflow: hidden;
text-align: right;
}
.card .equip-list {
width: 100%;
display: grid;

View file

@ -140,6 +140,7 @@
<% include(sys.specialTitle, {en: 'METAL' , cn: '驱动盘信息' }) %>
</div>
{{if charData.equip_score !== false}}
<div class="equip-stats">
<div class="equip-score {{charData.equip_comment}}">
<div class="comment-box">
<div class="comment">{{charData.equip_comment}}</div>
@ -149,6 +150,19 @@
<span class="subt"></span>
</div>
</div>
<div class="property-stats">
{{set stats = charData.propertyStats.slice(0, 9)}}
{{each stats item}}
<div class="stat-item {{item.weight == 1 ? 'great' : (item.weight >= 0.75 ? 'good' : (item.weight > 0 ? 'useful' : 'useless'))}}">
<span class="title"><span class="count">{{item.count}}</span> {{item.name}}</span>
<span class="value">+{{item.value}}</span>
</div>
{{/each}}
<% for (let i = 0; i < 9-stats.length; i++) { %>
<div class="stat-item"></div>
<% } %>
</div>
</div>
{{/if}}
<div class="equip-list">
{{each charData.equip_final equip}}

View file

@ -478,12 +478,20 @@
}
}
.equip-stats {
display: flex;
padding: 0 1.8em;
height: 6em;
.equip-score {
border: #707070 solid;
border-width: 0.2em 0 0.2em 0.2em;
border-radius: 0.6em 0 0 0.6em;
display: flex;
justify-content: center;
font-size: 1.2em;
font-size: 1em;
align-items: center;
gap: 0.2em;
width: 30%;
.comment-box {
font-size: 1.2em;
width: 2em;
@ -510,6 +518,76 @@
}
}
.property-stats {
width: 70%;
height: 100%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
font-size: 0.8em;
align-items: center;
border: #707070 solid;
border-width: 0.2em;
border-radius: 0 0.6em 0.6em 0;
overflow: hidden;
.stat-item {
width: 33.33%;
height: 33.33%;
padding: 0 0.2em;
position: relative;
display: flex;
align-items: center;
white-space: nowrap;
color: #eee;
border: #707070 0.1em solid;
&:nth-child(7) {
border-radius: 0 0.4em 0 0;
}
&:nth-child(9) {
border-radius: 0 0 0.4em 0;
}
&.great {
color: rgb(249, 189, 64);
}
&.good {
color: rgb(238, 207, 139);
}
&.useless {
color: #999999;
}
span.title {
padding-left: 0.1em;
text-align: left;
width: 48%;
span.count {
display: inline-block;
text-align: center;
background-color: black;
width: 1.6em;
height: 1.6em;
border: #696969 0.15em solid;
border-radius: 0.4em;
}
}
span.value {
padding-right: 0.2em;
width: 52%;
overflow: hidden;
text-align: right;
}
}
}
}
.equip-list {
width: 100%;
display: grid;