mirror of
https://github.com/ZZZure/ZZZ-Plugin.git
synced 2025-12-16 13:17:32 +00:00
feat: 角色命座
This commit is contained in:
parent
5830178362
commit
73715f015f
12 changed files with 324 additions and 14 deletions
|
|
@ -208,6 +208,13 @@ const helpData = [
|
|||
needSK: false,
|
||||
commands: ['角色名+天赋[+等级]'],
|
||||
},
|
||||
{
|
||||
title: '角色意象影画图鉴',
|
||||
desc: '查看角色命座图鉴',
|
||||
needCK: false,
|
||||
needSK: false,
|
||||
commands: ['角色名+命座', '角色名+意象', '角色名+影画'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
21
apps/wiki.js
21
apps/wiki.js
|
|
@ -43,10 +43,15 @@ export class Wiki extends ZZZPlugin {
|
|||
reg: `${rulePrefix}(.*)天赋(.*)$`,
|
||||
fnc: 'skills',
|
||||
},
|
||||
{
|
||||
reg: `${rulePrefix}(.*)(意象影画|意象|影画|命座)$`,
|
||||
fnc: 'cinema',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
async skills() {
|
||||
logger.debug('skills');
|
||||
const reg = new RegExp(`${rulePrefix}(.*)天赋(.*)$`);
|
||||
const charname = this.e.msg.match(reg)[4];
|
||||
if (!charname) return false;
|
||||
|
|
@ -94,4 +99,20 @@ export class Wiki extends ZZZPlugin {
|
|||
};
|
||||
await this.render('skills/index.html', finalData);
|
||||
}
|
||||
async cinema() {
|
||||
const reg = new RegExp(`${rulePrefix}(.*)(意象影画|意象|影画|命座)$`);
|
||||
const charname = this.e.msg.match(reg)[4];
|
||||
if (!charname) return false;
|
||||
const charData = await getHakushCharacterData(charname);
|
||||
const cinemaData = charData?.Talent;
|
||||
if (!cinemaData) {
|
||||
await this.reply(`未找到${charname}的数据`);
|
||||
return false;
|
||||
}
|
||||
await charData.get_assets();
|
||||
const finalData = {
|
||||
charData,
|
||||
};
|
||||
await this.render('cinema/index.html', finalData);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,3 +7,5 @@ export const ZZZ_CHARACTER = HAKUSH_API + '/character',
|
|||
export const ZZZ_NEW = `${HAKUSH_BASE}/new.json`,
|
||||
ZZZ_ALL_CHAR = `${HAKUSH_BASE}/data/character.json`,
|
||||
ZZZ_ALL_WEAPON = `${HAKUSH_BASE}/data/weapon.json`;
|
||||
|
||||
export const ZZZ_UI = `${HAKUSH_BASE}/UI`;
|
||||
|
|
|
|||
|
|
@ -165,3 +165,13 @@ export const getHakushWeapon = async weaponId => {
|
|||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取Hakush UI
|
||||
* @param {string} filename
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export const getHakushUI = async filename => {
|
||||
const result = await downloadHakushFile('ZZZ_UI', 'HAKUSH_UI_PATH', filename);
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,4 +21,5 @@ export const HAKUSH_CHARACTER_DATA_PATH = path.join(
|
|||
dataResourcesPath,
|
||||
'hakush/data/character'
|
||||
),
|
||||
HAKUSH_WEAPON_DATA_PATH = path.join(dataResourcesPath, 'hakush/data/weapon');
|
||||
HAKUSH_WEAPON_DATA_PATH = path.join(dataResourcesPath, 'hakush/data/weapon'),
|
||||
HAKUSH_UI_PATH = path.join(imageResourcesPath, 'hakush/ui');
|
||||
|
|
|
|||
|
|
@ -74,7 +74,12 @@ export const downloadHakushFile = async (base, localBase, filename = '') => {
|
|||
// 关闭文件
|
||||
fs.closeSync(file);
|
||||
// 返回文件内容
|
||||
// 如果是JSON文件,返回JSON对象
|
||||
if (filename.endsWith('.json')) {
|
||||
return JSON.parse(content.toString());
|
||||
} else {
|
||||
return filepath;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { getSquareAvatar } from '../../lib/download.js';
|
||||
import { getHakushUI, getSquareAvatar } from '../../lib/download.js';
|
||||
/**
|
||||
* @typedef {Object} StatsData
|
||||
* @property {number} Armor
|
||||
|
|
@ -512,6 +512,38 @@ class TalentLevel {
|
|||
this.Name = data.Name;
|
||||
this.Desc = data.Desc;
|
||||
this.Desc2 = data.Desc2;
|
||||
|
||||
/** @type {string} */
|
||||
this.description = this.Desc
|
||||
? '<div class="line">' +
|
||||
this.Desc.replace(
|
||||
/<IconMap:Icon_(\w+)>/g,
|
||||
'<span class="skill-icon $1"></span>'
|
||||
)
|
||||
.replace(
|
||||
/<color=#(\w+?)>(.+?)<\/color>/g,
|
||||
'<span style="color:#$1"><strong>$2</strong></span>'
|
||||
)
|
||||
.split('\n')
|
||||
.join('</div><div class="line">') +
|
||||
'</div>'
|
||||
: '';
|
||||
|
||||
/** @type {string} */
|
||||
this.description2 = this.Desc2
|
||||
? '<div class="line">' +
|
||||
this.Desc2.replace(
|
||||
/<IconMap:Icon_(\w+)>/g,
|
||||
'<span class="skill-icon $1"></span>'
|
||||
)
|
||||
.replace(
|
||||
/<color=#(\w+?)>(.+?)<\/color>/g,
|
||||
'<span style="color:#$1"><strong>$2</strong></span>'
|
||||
)
|
||||
.split('\n')
|
||||
.join('</div><div class="line">') +
|
||||
'</div>'
|
||||
: '';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -555,7 +587,7 @@ export class Character {
|
|||
this.Stats = new Stats(data.Stats);
|
||||
this.Level = {};
|
||||
this.ExtraLevel = {};
|
||||
this.Talent = {};
|
||||
this.Talent = [];
|
||||
|
||||
for (const [key, value] of Object.entries(data.Level)) {
|
||||
this.Level[key] = new Level(value);
|
||||
|
|
@ -566,13 +598,19 @@ export class Character {
|
|||
this.Skill = new Skill(data.Skill);
|
||||
this.Passive = new Passive(data.Passive);
|
||||
|
||||
for (const [key, value] of Object.entries(data.Talent)) {
|
||||
this.Talent[key] = new TalentLevel(value);
|
||||
for (const [_, value] of Object.entries(data.Talent)) {
|
||||
this.Talent.push(new TalentLevel(value));
|
||||
}
|
||||
}
|
||||
|
||||
async get_assets() {
|
||||
const result = await getSquareAvatar(this.Id);
|
||||
this.square_icon = result;
|
||||
await this.get_cinema_assets();
|
||||
}
|
||||
|
||||
async get_cinema_assets() {
|
||||
const result = await getHakushUI(`Mindscape_${this.Id}_3.webp`);
|
||||
this.cinema_image = result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
86
resources/cinema/index.css
Normal file
86
resources/cinema/index.css
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
.char-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 1em;
|
||||
gap: 1em;
|
||||
}
|
||||
.char-info .avatar {
|
||||
width: 5em;
|
||||
aspect-ratio: 1;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.char-info .avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.char-info .info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
.char-info .info .name {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 0.5em;
|
||||
}
|
||||
.char-info .info .name .simple {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.char-info .info .description {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.cinema {
|
||||
padding: 1em;
|
||||
}
|
||||
.cinema .header {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.cinema .title {
|
||||
color: white;
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
}
|
||||
.cinema .subtitle {
|
||||
color: #6666ff;
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
.cinema .content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
.cinema .section {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.cinema .section-title {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.cinema .section-content {
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.cinema .highlight {
|
||||
color: #ffd700;
|
||||
}
|
||||
.cinema .skill-tag {
|
||||
display: inline-block;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.cinema .image-container {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.cinema .character-image {
|
||||
max-width: 100%;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
43
resources/cinema/index.html
Normal file
43
resources/cinema/index.html
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{{extend defaultLayout}}
|
||||
|
||||
{{block 'css'}}
|
||||
<link rel="stylesheet" href="{{@sys.currentPath}}/index.css">
|
||||
{{/block}}
|
||||
|
||||
{{block 'main'}}
|
||||
<div class="char-info">
|
||||
<div class="avatar">
|
||||
<img src="{{charData.square_icon}}" alt="Avatar">
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name">
|
||||
<div class="simple">{{charData.PartnerInfo.Name}}</div>
|
||||
<div class="full">{{charData.PartnerInfo.FullName}}</div>
|
||||
</div>
|
||||
<div class="description no-zzz-font">
|
||||
<div class="f">{{@charData.PartnerInfo.ImpressionF}}</div>
|
||||
<div class="m">{{@charData.PartnerInfo.ImpressionM}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cinema">
|
||||
<div class="header">
|
||||
<h1 class="title">意象影画</h1>
|
||||
<h2 class="subtitle">CINEMA</h2>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{each charData.Talent talent}}
|
||||
<div class="section">
|
||||
<h3 class="section-title">{{talent.Level}}. {{talent.Name}}</h3>
|
||||
<div class="section-content no-zzz-font">
|
||||
{{@talent.description}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="image-container">
|
||||
<img src="{{charData.cinema_image}}" alt="角色插图" class="character-image">
|
||||
</div>
|
||||
<div style="text-align: center; font-size: 1em; color: #666; margin: 2em 0;">数据来源于Hakush</div>
|
||||
{{/block}}
|
||||
95
resources/cinema/index.scss
Normal file
95
resources/cinema/index.scss
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
.char-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 1em;
|
||||
gap: 1em;
|
||||
.avatar {
|
||||
width: 5em;
|
||||
aspect-ratio: 1;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 0.5em;
|
||||
.simple {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
.description {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cinema {
|
||||
padding: 1em;
|
||||
|
||||
.header {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: white;
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #6666ff;
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.section-content {
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.skill-tag {
|
||||
display: inline-block;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.character-image {
|
||||
max-width: 100%;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,14 +5,10 @@
|
|||
@font-face {
|
||||
font-family: "tttgbnumber";
|
||||
src: url("../../../../../genshin/resources/font/tttgbnumber.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "HYWenHei-55W";
|
||||
src: url("../../../../../genshin/resources/font/HYWenHei-55W.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
.zzz-font {
|
||||
font-family: "zzz", "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
|
|
@ -21,6 +17,10 @@
|
|||
.no-zzz-font {
|
||||
font-family: "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
}
|
||||
.no-zzz-font strong,
|
||||
.no-zzz-font b {
|
||||
font-family: "zzz", "tttgbnumber", "HYWenHei-55W", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
.rank-icon {
|
||||
aspect-ratio: 1;
|
||||
|
|
|
|||
|
|
@ -8,15 +8,11 @@
|
|||
@font-face {
|
||||
font-family: 'tttgbnumber';
|
||||
src: url('../../../../../genshin/resources/font/tttgbnumber.ttf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'HYWenHei-55W';
|
||||
src: url('../../../../../genshin/resources/font/HYWenHei-55W.ttf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.zzz-font {
|
||||
|
|
@ -29,6 +25,12 @@
|
|||
font-family: 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
||||
'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
strong,
|
||||
b {
|
||||
font-family: 'zzz', 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system,
|
||||
BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
||||
'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.rank-icon {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue