//=============================================================================
// PatchNotes_MZ.js
//=============================================================================
/*:
* @target MZ
* @plugindesc [PatchNotes_MZ] Ajoute "Patch Notes" sur l'écran titre.
* @author Bertran
*
* @param commandName
* @text Nom du bouton
* @desc Texte affiché sur l'écran titre.
* @type string
* @default PATCH NOTES
*
* @param entries
* @text Entrées de patch notes
* @type struct<Entry>[]
* @default []
*
* @param scrollSpeed
* @text Vitesse de défilement
* @type number
* @min 1
* @max 10
* @default 3
*
*/
/*~struct~Entry:
*
* @param version
* @text Version
* @type string
* @default Version X.X.X
*
* @param date
* @text Date
* @type string
* @default
*
* @param notes
* @text Contenu
* @type multiline_string
* @default - Nouveautés
*/
(() => {
'use strict';
// -------------------------------------------------------------------------
// Récupération des paramètres — cherche avec plusieurs variantes du nom
// au cas où le gestionnaire de plugins utilise un nom légèrement différent
// -------------------------------------------------------------------------
const NAMES = ['PatchNotes_MZ', 'patchnotes_mz', 'PatchNotes', 'patchnotes'];
let params = {};
for (const n of NAMES) {
const p = PluginManager.parameters(n);
if (p && (p.commandName || p.entries)) { params = p; break; }
}
// Fallback : parcourir TOUS les paramètres enregistrés
if (!params.commandName && !params.entries) {
for (const key of Object.keys(PluginManager._parameters || {})) {
if (key.toLowerCase().includes('patchnote')) {
params = PluginManager._parameters[key];
break;
}
}
}
const COMMAND_NAME = String(params.commandName || 'PATCH NOTES');
const SCROLL_SPEED = Number(params.scrollSpeed || 3);
function parseEntries(raw) {
if (!raw || raw.trim() === '' || raw.trim() === '[]') return [];
let arr;
try { arr = JSON.parse(raw); } catch(e) { return []; }
if (!Array.isArray(arr)) return [];
const result = [];
for (const item of arr) {
let obj;
try { obj = (typeof item === 'string') ? JSON.parse(item) : item; }
catch(e) { continue; }
if (!obj) continue;
result.push({
version : String(obj.version || ''),
date : String(obj.date || ''),
notes : String(obj.notes || '').replace(/\\n/g, '\n'),
});
}
return result;
}
const ENTRIES = parseEntries(params.entries);
// -------------------------------------------------------------------------
// Menu titre
// -------------------------------------------------------------------------
const _makeCommandList = Window_TitleCommand.prototype.makeCommandList;
Window_TitleCommand.prototype.makeCommandList = function() {
_makeCommandList.call(this);
this.addCommand(COMMAND_NAME, 'patchNotes');
};
const _createCommandWindow = Scene_Title.prototype.createCommandWindow;
Scene_Title.prototype.createCommandWindow = function() {
_createCommandWindow.call(this);
this._commandWindow.setHandler('patchNotes', this.commandPatchNotes.bind(this));
};
Scene_Title.prototype.commandPatchNotes = function() {
this._commandWindow.close();
SceneManager.push(Scene_PatchNotes);
};
// =========================================================================
// Scene_PatchNotes
// =========================================================================
function Scene_PatchNotes() { this.initialize(...arguments); }
Scene_PatchNotes.prototype = Object.create(Scene_MenuBase.prototype);
Scene_PatchNotes.prototype.constructor = Scene_PatchNotes;
Scene_PatchNotes.prototype.create = function() {
Scene_MenuBase.prototype.create.call(this);
const rect = new Rectangle(0, 0, Graphics.boxWidth, Graphics.boxHeight);
this._patchWindow = new Window_PatchNotes(rect);
this.addWindow(this._patchWindow);
};
Scene_PatchNotes.prototype.update = function() {
Scene_MenuBase.prototype.update.call(this);
if (Input.isTriggered('cancel')) {
SoundManager.playCancel();
this.popScene();
}
};
// =========================================================================
// Window_PatchNotes
// =========================================================================
function Window_PatchNotes() { this.initialize(...arguments); }
Window_PatchNotes.prototype = Object.create(Window_Scrollable.prototype);
Window_PatchNotes.prototype.constructor = Window_PatchNotes;
Window_PatchNotes.prototype.initialize = function(rect) {
Window_Scrollable.prototype.initialize.call(this, rect);
this.refresh();
};
Window_PatchNotes.prototype.scrollBlockHeight = function() { return this.lineHeight(); };
Window_PatchNotes.prototype.overallHeight = function() { return this._totalHeight || this.innerHeight; };
Window_PatchNotes.prototype.isScrollEnabled = function() { return true; };
Window_PatchNotes.prototype.refresh = function() {
const lh = this.lineHeight();
const pad = this.itemPadding();
const iw = this.innerWidth - pad * 2;
let y = pad;
this.contents.clear();
if (ENTRIES.length === 0) {
this._totalHeight = this.innerHeight;
this.contents.resize(this.innerWidth, this._totalHeight);
this.resetTextColor();
// Affiche aussi les params bruts pour aider au debug
const debugLine = 'Params: cmd="' + COMMAND_NAME + '" entries="' + (params.entries || '') + '"';
this.contents.fontSize = 14;
this.contents.drawText(debugLine, pad, 20, iw, lh);
this.contents.fontSize = $gameSystem.mainFontSize();
this.contents.drawText(
'Aucune note de mise à jour disponible.',
pad, Math.floor(this.innerHeight / 2 - lh / 2), iw, lh, 'center'
);
return;
}
// Calculer hauteur totale
let totalH = pad;
for (const e of ENTRIES) {
totalH += lh + 8;
if (e.date) totalH += lh;
totalH += 12;
totalH += e.notes.split('\n').length * lh;
totalH += lh;
}
totalH += pad;
this._totalHeight = Math.max(totalH, this.innerHeight);
this.contents.resize(this.innerWidth, this._totalHeight);
for (const entry of ENTRIES) {
this.changeTextColor(ColorManager.systemColor());
const fs = this.contents.fontSize;
this.contents.fontSize = fs + 4;
this.contents.drawText(entry.version, pad, y, iw, lh);
this.contents.fontSize = fs;
y += lh + 8;
if (entry.date) {
this.changeTextColor(ColorManager.textColor(8));
this.contents.drawText(entry.date, pad, y, iw, lh);
y += lh;
}
this.contents.fillRect(pad, y + 4, iw, 2, ColorManager.textColor(7));
y += 12;
this.resetTextColor();
for (const line of entry.notes.split('\n')) {
this.contents.drawText(line, pad + 8, y, iw - 8, lh);
y += lh;
}
y += lh;
}
};
Window_PatchNotes.prototype.update = function() {
Window_Scrollable.prototype.update.call(this);
if (Input.isPressed('down')) this.smoothScrollDown(SCROLL_SPEED);
if (Input.isPressed('up')) this.smoothScrollUp(SCROLL_SPEED);
};
})();
// ============================================================================
// PATCH : Ajout du retour avec Échap / B / clic droit
// ============================================================================
(() => {
// Ajoute un handler de retour à la fenêtre Patch Notes
const _PatchNotes_initialize = Window_PatchNotes.prototype.initialize;
Window_PatchNotes.prototype.initialize = function(rect) {
_PatchNotes_initialize.call(this, rect);
this.setHandler('cancel', () => {
SoundManager.playCancel();
SceneManager.pop();
});
this.activate();
};
// Permet aussi de quitter même si la fenêtre n’a pas le focus
const _Scene_PatchNotes_update = Scene_PatchNotes.prototype.update;
Scene_PatchNotes.prototype.update = function() {
_Scene_PatchNotes_update.call(this);
if (Input.isTriggered('cancel') || TouchInput.isCancelled()) {
SoundManager.playCancel();
SceneManager.pop();
}
};
})();
To embed this project on your website, copy the following code and paste it into your website's HTML: