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,
|
needSK: false,
|
||||||
commands: ['角色名+天赋[+等级]'],
|
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}(.*)天赋(.*)$`,
|
reg: `${rulePrefix}(.*)天赋(.*)$`,
|
||||||
fnc: 'skills',
|
fnc: 'skills',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
reg: `${rulePrefix}(.*)(意象影画|意象|影画|命座)$`,
|
||||||
|
fnc: 'cinema',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async skills() {
|
async skills() {
|
||||||
|
logger.debug('skills');
|
||||||
const reg = new RegExp(`${rulePrefix}(.*)天赋(.*)$`);
|
const reg = new RegExp(`${rulePrefix}(.*)天赋(.*)$`);
|
||||||
const charname = this.e.msg.match(reg)[4];
|
const charname = this.e.msg.match(reg)[4];
|
||||||
if (!charname) return false;
|
if (!charname) return false;
|
||||||
|
|
@ -94,4 +99,20 @@ export class Wiki extends ZZZPlugin {
|
||||||
};
|
};
|
||||||
await this.render('skills/index.html', finalData);
|
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`,
|
export const ZZZ_NEW = `${HAKUSH_BASE}/new.json`,
|
||||||
ZZZ_ALL_CHAR = `${HAKUSH_BASE}/data/character.json`,
|
ZZZ_ALL_CHAR = `${HAKUSH_BASE}/data/character.json`,
|
||||||
ZZZ_ALL_WEAPON = `${HAKUSH_BASE}/data/weapon.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;
|
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,
|
dataResourcesPath,
|
||||||
'hakush/data/character'
|
'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);
|
fs.closeSync(file);
|
||||||
// 返回文件内容
|
// 返回文件内容
|
||||||
return JSON.parse(content.toString());
|
// 如果是JSON文件,返回JSON对象
|
||||||
|
if (filename.endsWith('.json')) {
|
||||||
|
return JSON.parse(content.toString());
|
||||||
|
} else {
|
||||||
|
return filepath;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getSquareAvatar } from '../../lib/download.js';
|
import { getHakushUI, getSquareAvatar } from '../../lib/download.js';
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} StatsData
|
* @typedef {Object} StatsData
|
||||||
* @property {number} Armor
|
* @property {number} Armor
|
||||||
|
|
@ -512,6 +512,38 @@ class TalentLevel {
|
||||||
this.Name = data.Name;
|
this.Name = data.Name;
|
||||||
this.Desc = data.Desc;
|
this.Desc = data.Desc;
|
||||||
this.Desc2 = data.Desc2;
|
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.Stats = new Stats(data.Stats);
|
||||||
this.Level = {};
|
this.Level = {};
|
||||||
this.ExtraLevel = {};
|
this.ExtraLevel = {};
|
||||||
this.Talent = {};
|
this.Talent = [];
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(data.Level)) {
|
for (const [key, value] of Object.entries(data.Level)) {
|
||||||
this.Level[key] = new Level(value);
|
this.Level[key] = new Level(value);
|
||||||
|
|
@ -566,13 +598,19 @@ export class Character {
|
||||||
this.Skill = new Skill(data.Skill);
|
this.Skill = new Skill(data.Skill);
|
||||||
this.Passive = new Passive(data.Passive);
|
this.Passive = new Passive(data.Passive);
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(data.Talent)) {
|
for (const [_, value] of Object.entries(data.Talent)) {
|
||||||
this.Talent[key] = new TalentLevel(value);
|
this.Talent.push(new TalentLevel(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get_assets() {
|
async get_assets() {
|
||||||
const result = await getSquareAvatar(this.Id);
|
const result = await getSquareAvatar(this.Id);
|
||||||
this.square_icon = result;
|
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-face {
|
||||||
font-family: "tttgbnumber";
|
font-family: "tttgbnumber";
|
||||||
src: url("../../../../../genshin/resources/font/tttgbnumber.ttf");
|
src: url("../../../../../genshin/resources/font/tttgbnumber.ttf");
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "HYWenHei-55W";
|
font-family: "HYWenHei-55W";
|
||||||
src: url("../../../../../genshin/resources/font/HYWenHei-55W.ttf");
|
src: url("../../../../../genshin/resources/font/HYWenHei-55W.ttf");
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
.zzz-font {
|
.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;
|
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 {
|
.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;
|
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 {
|
.rank-icon {
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,11 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'tttgbnumber';
|
font-family: 'tttgbnumber';
|
||||||
src: url('../../../../../genshin/resources/font/tttgbnumber.ttf');
|
src: url('../../../../../genshin/resources/font/tttgbnumber.ttf');
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'HYWenHei-55W';
|
font-family: 'HYWenHei-55W';
|
||||||
src: url('../../../../../genshin/resources/font/HYWenHei-55W.ttf');
|
src: url('../../../../../genshin/resources/font/HYWenHei-55W.ttf');
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zzz-font {
|
.zzz-font {
|
||||||
|
|
@ -29,6 +25,12 @@
|
||||||
font-family: 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system,
|
font-family: 'tttgbnumber', 'HYWenHei-55W', system-ui, -apple-system,
|
||||||
BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
|
||||||
'Open Sans', 'Helvetica Neue', sans-serif;
|
'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 {
|
.rank-icon {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue