/*: * @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]; } })();