提供一个语音台词写法的范例
This commit is contained in:
parent
d9532d354d
commit
1f67b90fec
|
@ -4,6 +4,7 @@ import cards from "./card.js";
|
|||
import pinyins from "./pinyin.js";
|
||||
import skills from "./skill.js";
|
||||
import translates from "./translate.js";
|
||||
import voices from "./voices.json";
|
||||
|
||||
game.import("character", function () {
|
||||
return {
|
||||
|
@ -98,7 +99,7 @@ game.import("character", function () {
|
|||
},
|
||||
card: { ...cards },
|
||||
skill: { ...skills },
|
||||
translate: { ...translates },
|
||||
translate: { ...translates, ...voices },
|
||||
pinyins: { ...pinyins },
|
||||
};
|
||||
});
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"#yuri_xingdong1": "では、オペレーション・スターーート!!",
|
||||
"#yuri_xingdong2": "では、オペレーション・スタート!",
|
||||
"#yuri_xingdong3": "では、オペレーションスタート!",
|
||||
"#yuri_xingdong_gain1": "…さすがね、あたしの勘。",
|
||||
"#yuri_xingdong_gain2": "あたしの予想ではね。",
|
||||
"#yuri_wangxi1": "賢明ね。これでようやくあなたにも戦線で戦う目的が生まれたってわけね。",
|
||||
"#yuri_wangxi2": "落ち着いて…ここは地獄なんかじゃないわ。",
|
||||
"#key_yuri:die": "ひどい…リーダーね。"
|
||||
}
|
|
@ -1482,8 +1482,9 @@ export class Game {
|
|||
* @typedef {[string,number]|string|number|boolean} audioInfo
|
||||
* @typedef {{audio: audioInfo, audioname?:string[], audioname2?:{[playerName: string]: audioInfo}}} skillInfo
|
||||
* @param { string } skill 技能名
|
||||
* @param { Player | string } [player] 角色/角色名
|
||||
* @param { Player | Object | string } [player] 角色/角色名
|
||||
* @param { skillInfo | audioInfo } [skillInfo] 预设的skillInfo/audioInfo(转为skillInfo),覆盖lib.skill[skill]
|
||||
* @param { boolean | undefined } [useRawAudio]
|
||||
* @returns { string[] } 语音地址列表
|
||||
* @example
|
||||
* ```js
|
||||
|
@ -1515,7 +1516,7 @@ export class Game {
|
|||
* //如果key中包含发动技能的角色名player,则直接改用info.audioname2[player]来播放语音
|
||||
* ```
|
||||
*/
|
||||
parseSkillAudio(skill, player, skillInfo) {
|
||||
parseSkillAudio(skill, player, skillInfo, useRawAudio) {
|
||||
if (typeof player === "string") player = { name: player };
|
||||
else if (typeof player !== "object" || player === null) player = {};
|
||||
|
||||
|
@ -1527,7 +1528,7 @@ export class Game {
|
|||
if (!history.includes(skill)) return true;
|
||||
if (history[0] === skill) return false;
|
||||
//deadlock
|
||||
throw new RangeError(`parseSkillAudio: ${skill} in `, history, ` forms a deadlock`);
|
||||
throw new RangeError(`parseSkillAudio: ${skill} in ${ history }forms a deadlock`);
|
||||
};
|
||||
|
||||
const getName = (filter) => {
|
||||
|
@ -1538,7 +1539,7 @@ export class Game {
|
|||
if (result) return result;
|
||||
if (!name) return result;
|
||||
if (filter(name)) return name;
|
||||
let tempname = get.character(name, 4).find((tag) => tag.startsWith("tempname:"));
|
||||
let tempname = get.character(name).trashBin.find((tag) => tag.startsWith("tempname:"));
|
||||
if (!tempname) return result;
|
||||
tempname = tempname
|
||||
.split(":")
|
||||
|
@ -1555,7 +1556,7 @@ export class Game {
|
|||
* @param {skillInfo} [skillInfo]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getAudioList(skill, options, skillInfo) {
|
||||
function getAudioList(skill, options, skillInfo, useRawAudio) {
|
||||
const info = skillInfo || lib.skill[skill];
|
||||
if (!info) {
|
||||
console.error(new ReferenceError(`parseSkillAudio: Cannot find ${skill} in lib.skill`));
|
||||
|
@ -1610,7 +1611,7 @@ export class Game {
|
|||
)
|
||||
format = ".mp3";
|
||||
if (path && format) return parseAudio(audioInfo, options, [true, 2]);
|
||||
return [`${path}${audioInfo}${format}`];
|
||||
return [useRawAudio ? audioInfo : `${path}${audioInfo}${format}`];
|
||||
}
|
||||
|
||||
let _audioname = getName((i) => audioname.includes(i));
|
||||
|
@ -1622,13 +1623,32 @@ export class Game {
|
|||
const audioList = [];
|
||||
list[2] = parseInt(list[2]);
|
||||
for (let i = 1; i <= list[2]; i++) {
|
||||
audioList.push(`${list[1] || "skill"}/${skill}${_audioname}${i}.${list[3] || "mp3"}`);
|
||||
if(useRawAudio) audioList.push(`${skill}${_audioname}${i}`);
|
||||
else audioList.push(`${list[1] || "skill"}/${skill}${_audioname}${i}.${list[3] || "mp3"}`);
|
||||
}
|
||||
return audioList;
|
||||
}
|
||||
|
||||
return getAudioList(skill, { audioname: [], history: [] }, skillInfo);
|
||||
}
|
||||
/**
|
||||
* 根据skill中的audio,audioname,audioname2和player来获取技能台词列表
|
||||
* @typedef {[string,number]|string|number|boolean} audioInfo
|
||||
* @typedef {{audio: audioInfo, audioname?:string[], audioname2?:{[playerName: string]: audioInfo}}} skillInfo
|
||||
* @param { string } skill 技能名
|
||||
* @param { Player | Object | string } [player] 角色/角色名
|
||||
* @param { skillInfo | audioInfo } [skillInfo] 预设的skillInfo/audioInfo(转为skillInfo),覆盖lib.skill[skill]
|
||||
* @returns { string[] } 语音地址列表
|
||||
*/
|
||||
parseSkillText(skill, player, skillInfo){
|
||||
const audios = game.parseSkillAudio(skill, player, skillInfo, true);
|
||||
const voiceMap = [];
|
||||
audios.forEach(audioname => {
|
||||
const voiceText = lib.translate[`#${audioname}`];
|
||||
if(voiceText) voiceMap.push(voiceText);
|
||||
});
|
||||
return voiceMap;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param { string } skill
|
||||
|
|
|
@ -3494,14 +3494,14 @@ export class Click {
|
|||
} else {
|
||||
// 样式一
|
||||
//TODO: 这里的数据也暂时没有改成新格式,需要后续的修改
|
||||
const nameInfo = get.character(name);
|
||||
const introduction = ui.create.div(".characterintro", uiintro),
|
||||
showCharacterNamePinyin = lib.config.show_characternamepinyin;
|
||||
if (showCharacterNamePinyin != "doNotShow") {
|
||||
const characterIntroTable = ui.create.div(".character-intro-table", introduction),
|
||||
span = document.createElement("span");
|
||||
span.style.fontWeight = "bold";
|
||||
const nameInfo = get.character(name),
|
||||
exInfo = nameInfo.trashBin,
|
||||
const exInfo = nameInfo.trashBin,
|
||||
characterName =
|
||||
exInfo && exInfo.includes("ruby") ? lib.translate[name] : get.rawName2(name);
|
||||
span.innerHTML = characterName;
|
||||
|
@ -3632,8 +3632,45 @@ export class Click {
|
|||
const htmlParser = document.createElement("body");
|
||||
htmlParser.innerHTML = get.characterIntro(name);
|
||||
Array.from(htmlParser.childNodes).forEach((value) => introduction.appendChild(value));
|
||||
//添加技能语音部分
|
||||
const dieAudio = lib.translate[`#${name}:die`];
|
||||
const skillAudioMap = new Map();
|
||||
nameInfo.skills.forEach(skill => {
|
||||
const voiceMap = game.parseSkillText(skill, name, null, true);
|
||||
if(voiceMap.length) skillAudioMap.set(skill, voiceMap);
|
||||
});
|
||||
if (dieAudio || skillAudioMap.size > 0){
|
||||
introduction.appendChild(document.createElement("hr"));
|
||||
const skillNameSpan = document.createElement("span");
|
||||
skillNameSpan.innerHTML = `技能台词<br>`;
|
||||
introduction.appendChild(skillNameSpan);
|
||||
|
||||
if(skillAudioMap.size > 0){
|
||||
skillAudioMap.forEach((texts, skill) => {
|
||||
const skillNameSpan = document.createElement("span"), skillNameSpanStyle = skillNameSpan.style;
|
||||
skillNameSpanStyle.fontWeight = "bold";
|
||||
skillNameSpan.innerHTML = `<br>${get.translation(skill)}<br>`;
|
||||
introduction.appendChild(skillNameSpan);
|
||||
texts.forEach((text, index) => {
|
||||
const skillTextSpan = document.createElement("span");
|
||||
skillTextSpan.innerHTML = `${index + 1}. ${text}<br>`;
|
||||
introduction.appendChild(skillTextSpan);
|
||||
})
|
||||
});
|
||||
}
|
||||
if(dieAudio){
|
||||
const skillNameSpan = document.createElement("span"), skillNameSpanStyle = skillNameSpan.style;
|
||||
skillNameSpanStyle.fontWeight = "bold";
|
||||
skillNameSpan.innerHTML = `<br>阵亡台词<br>`;
|
||||
introduction.appendChild(skillNameSpan);
|
||||
|
||||
const skillTextSpan = document.createElement("span");
|
||||
skillTextSpan.innerHTML = `${dieAudio}`;
|
||||
introduction.appendChild(skillTextSpan);
|
||||
}
|
||||
}
|
||||
const introduction2 = ui.create.div(".characterintro.intro2", uiintro);
|
||||
var list = get.character(name, 3) || [];
|
||||
var list = get.character(name).skills;
|
||||
var skills = ui.create.div(".characterskill", uiintro);
|
||||
if (lib.config.touchscreen) {
|
||||
lib.setScroll(introduction);
|
||||
|
|
Loading…
Reference in New Issue