prison-brave/js/plugins/IM_StateNoteControlCharacter.js
2025-08-28 23:34:50 -05:00

124 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*:
* @target MZ
* @plugindesc \STATE[n] でステートのメモ欄、\SKILL[n] でスキルの説明欄を表示(<タグ> 除去。v1.1.0
* @author Umu
*
* @help
* ■ 使い方
* イベントの「文章の表示」に以下のように記述してください。
* \STATE[10] # ステート ID10 のメモ欄テキストを挿入
* \SKILL[25] # スキル ID25 の説明テキストを挿入
*
* メモ欄・説明欄に改行があれば、そのまま改行されます。
* <タグ> で囲まれた部分はすべて削除されます。
*
* ■ 仕様
* ・Window_Base.convertEscapeCharacters の処理後に、独自制御文字を追加で処理します。
* ・制御文字は大文字小文字を問いません(例: \skill[1] も可)。
* ・無効な ID や空文字の場合は空文字列を返します。
*
* ●\STATE[n] : $dataStates[n].note を取得し、/<[^>]*>/g で <タグ> を除去
* ●\SKILL[n] : $dataSkills[n].description を取得し、同様に <タグ> を除去
*
* プラグインコマンド・パラメータはありません。
*
* ■ 利用規約
* MIT ライセンス (LICENSE.txt 同梱)
*/
(() => {
'use strict';
/** <タグ> を取り除くための正規表現 */
const TAG_REGEX = /<[^>]*>/g;
/** 元の convertEscapeCharacters を保持 */
const _convertEscapeCharacters = Window_Base.prototype.convertEscapeCharacters;
/**
* 文章中の制御文字を変換
* @param {string} text
* @returns {string}
*/
Window_Base.prototype.convertEscapeCharacters = function (text) {
// 既存の制御文字を最初に処理
text = _convertEscapeCharacters.call(this, text);
// \SKILL[n] — スキル説明欄を挿入(英語向けに幅で折り返し)
text = text.replace(/\x1bSKILL\[(\d+)]/gi, (_, p1) => {
const id = Number(p1);
const skill = $dataSkills[id];
if (skill && typeof skill.description === 'string') {
const raw = skill.description.replace(TAG_REGEX, '').trim();
const tmp = new Bitmap(1, 1);
tmp.fontFace = 'MPLUS1Code-Regular';
tmp.fontSize = 26;
const pad = this?.padding ?? 12;
const maxWidth = Math.max(200, (this?.innerWidth ?? 480) - pad * 2);
return wrapTextToWidth_CC(raw, tmp, maxWidth);
}
return '';
});
// \STATE[n] — ステートメモ欄を挿入(英語向けに幅で折り返し)
text = text.replace(/\x1bSTATE\[(\d+)]/gi, (_, p1) => {
const id = Number(p1);
const state = $dataStates[id];
if (state && typeof state.note === 'string') {
const raw = state.note.replace(TAG_REGEX, '').trim();
const tmp = new Bitmap(1, 1);
tmp.fontFace = 'MPLUS1Code-Regular';
tmp.fontSize = 26;
const pad = this?.padding ?? 12;
const maxWidth = Math.max(200, (this?.innerWidth ?? 480) - pad * 2);
return wrapTextToWidth_CC(raw, tmp, maxWidth);
}
return '';
});
return text;
};
//============================================================
// Optional: English-friendly wrapping helpers
//============================================================
function wrapTextToWidth_CC(text, bitmap, maxWidth) {
if (!text) return '';
const lines = [];
const rawLines = String(text).replace(/\r\n?|\u2028/g, "\n").split('\n');
for (const raw of rawLines) {
const toks = raw.split(/(\s+)/);
let cur = '';
for (const tk of toks) {
const next = cur + tk;
if (bitmap.measureTextWidth(next) <= maxWidth) cur = next; else if (!cur) {
const parts = splitChars_CC(tk, bitmap, maxWidth);
for (let i = 0; i < parts.length - 1; i++) lines.push(parts[i]);
cur = parts[parts.length - 1];
} else {
if (cur.trim()) lines.push(cur.trimEnd());
const parts = splitChars_CC(tk, bitmap, maxWidth);
for (let i = 0; i < parts.length - 1; i++) lines.push(parts[i]);
cur = parts[parts.length - 1];
}
}
lines.push(cur.trimEnd());
}
return lines.join('\n');
}
function splitChars_CC(token, bitmap, maxWidth) {
const out = [];
let buf = '';
for (const ch of token) {
const next = buf + ch;
if (bitmap.measureTextWidth(next) <= maxWidth) buf = next; else {
if (buf) out.push(buf);
buf = ch;
}
}
if (buf) out.push(buf);
return out.length ? out : [token];
}
})();