//============================================================================= // RPG Maker MZ - IM_SceneMenu // // Copyright 2025 I'm moralist/min-pub.com All rights reserved. // This source code or any portion thereof must not be // reproduced or used without licensed in any manner whatsoever. //============================================================================= /*: * @target MZ * @plugindesc カスタムメニュープラグイン * @author I'm moralist * @base PluginCommonBase * @base PluginUtils * @base MPP_StateLevel * @orderAfter PluginCommonBase * @orderAfter SceneLewdStatus * @orderAfter PluginUtils * @orderAfter MPP_StateLevel * * @param actor * @text アクター * @desc スキル等表示アクター * @type actor * @default 0 * * @param braveLevel * @text 勇者レベル * @desc エロステ値を管理する変数を指定して下さい。 * @type variable * @default 0 * * @param prostituteLevel * @text 娼婦レベル * @desc エロステ値を管理する変数を指定して下さい。 * @type variable * @default 0 * * @requiredAssets img/pictures/500System/minimap * @requiredAssets img/system/im_menu/menu_effect * * @help IM_SceneMenu.js * * Version: 0.0.1 * * カスタムメニュー画面プラグイン */ (() => { "use strict"; const pluginName = "IM_SceneMenu"; const script = document.currentScript; const param = PluginManagerEx.createParameter(script); const MENU_TEXT_ITEM = "0900-020-n020-0"; const MENU_TEXT_SKILL = "0900-021-n021-0"; const MENU_TEXT_LEWD = "0900-022-n022-0"; const MENU_TEXT_STATE = "0900-023-n023-0"; const MENU_TEXT_MAP = "0900-034-n034-0"; const MENU_TEXT_OPTION = "0900-024-n024-0"; const MENU_TEXT_ALBUM = "0900-062-n062-0"; const MENU_TEXT_LOAD = "0900-025-n025-0"; const MENU_TEXT_SAVE = "0900-026-n026-0"; const MENU_TITLE_HP = "0900-027-n027-0"; const MENU_TITLE_MP = "0900-028-n028-0"; const MENU_TITLE_TP = "0900-029-n029-0"; const MENU_TITLE_BRAVE = "0900-030-n030-0"; const MENU_TITLE_PROSTITUTE = "0900-031-n031-0"; const MENU_TITLE_LV = "0900-033-n033-0"; const HELP_TEXT_CAUTION_ALBUM = "0900-063-n063-0"; const NOTICE_TEXT_ALBUM = "0900-067-n067-0"; //======================================================================== // クラス定義 (Window_CustomMenuCommand) //======================================================================== class Window_CustomMenuCommand extends Window_Command { constructor() { super(...arguments); this._lastCommandSymbol = null; this.selectLast(); this._canRepeat = false; } areMainCommandsEnabled() { return $gameParty.exists(); } makeCommandList() { const enabled = this.areMainCommandsEnabled() this.addCommand(TextResource.getText(MENU_TEXT_ITEM), "item", enabled); this.addCommand(TextResource.getText(MENU_TEXT_SKILL), "skill", enabled); this.addCommand(TextResource.getText(MENU_TEXT_LEWD), "lewdStatus", !!SceneLewdStatus); this.addCommand(TextResource.getText(MENU_TEXT_STATE), "badState", enabled); this.addCommand(TextResource.getText(MENU_TEXT_MAP), "map", enabled); this.addCommand(TextResource.getText(MENU_TEXT_OPTION), "options", enabled); this.addCommand(TextResource.getText(MENU_TEXT_ALBUM), "album", enabled); this.addCommand(TextResource.getText(MENU_TEXT_LOAD), "load", enabled); this.addCommand(TextResource.getText(MENU_TEXT_SAVE), "save", enabled); } drawItem(index) { const rect = this.itemLineRect(index); const align = this.itemTextAlign(); this.resetTextColor(); this.changePaintOpacity(this.isCommandEnabled(index)); this.contents.textColor = '#FFFFFF'; this.contents.fontFace = $gameSystem.mainFontFace(); this.contents.outlineWidth = 1; this.contents.fontSize = 42; this.drawText(this.commandName(index), rect.x, rect.y, rect.width, align); } initCommandPosition() { this._lastCommandSymbol = null; } selectLast() { this.selectSymbol(this._lastCommandSymbol); } select(index) { super.select(index); if (index >= 0 && this.maxItems() > 0 && !!this._helpWindow) { this.callUpdateHelp(); } } updateHelp() { super.updateHelp(); const index = this.index(); const command = this.commandSymbol(index); if (command === 'album') { this._helpWindow.setText(TextResource.getText(HELP_TEXT_CAUTION_ALBUM)); } else { this._helpWindow.clear(); } } itemHeight() { const spacing = this.rowSpacing(); return 70 + (spacing * 2); } }; //======================================================================== // クラス定義 (Window_ActorStates) //======================================================================== class Window_ActorStates extends Window_Base { constructor() { super(...arguments); this._actor = null; } setActor(actor) { if (this._actor !== actor) { this._actor = actor; this.refresh(); } } refresh() { this.paint(); } paint() { const actor = this._actor; const lineHeight = this.lineHeight(); const line1 = this.createLineBitmap(); line1.textColor = '#FFFFFF'; line1.fontFace = $gameSystem.mainFontFace(); line1.outlineWidth = 1; line1.fontSize = 48; line1.drawText(actor.name(), 0, 0, 320, lineHeight, 'left'); const hpGauge = this.createGaugeBitmap(400, TextResource.getText(MENU_TITLE_HP), actor.hp, actor.mhp, 10); line1.blt(hpGauge, 0, 0, hpGauge.width, hpGauge.height, 323, 0); const mpGauge = this.createGaugeBitmap(400, TextResource.getText(MENU_TITLE_MP), actor.mp, actor.mmp, 10); line1.blt(mpGauge, 0, 0, mpGauge.width, mpGauge.height, 744, 0); const line2 = this.createLineBitmap(); line2.textColor = '#BCBCBC'; line2.fontFace = $gameSystem.mainFontFace(); line2.outlineWidth = 1; line2.fontSize = 48; line2.drawText(actor.currentClass().name, 0, 0, 320, lineHeight, 'left'); const tpGauge = this.createGaugeBitmap(820, TextResource.getText(MENU_TITLE_TP), actor.tp, 100, 34, '#FFFFFF'); line2.blt(tpGauge, 0, 0, tpGauge.width, tpGauge.height, 323, 0); const braveLevel = PluginUtils.getVariables(param.braveLevel); const line3 = this.createLevelBitmap(MENU_TITLE_BRAVE, braveLevel); const prostituteLevel = PluginUtils.getVariables(param.prostituteLevel) ?? 0; const line4 = this.createLevelBitmap(MENU_TITLE_PROSTITUTE, prostituteLevel); const Level = $gameActors.actor(1).level; const line5 = this.createLevelBitmap(MENU_TITLE_LV, Level); const contentSx = 78; const contentSy = 68; this.contents.blt(line1, 0, 0, line1.width, line1.height, contentSx, contentSy); this.contents.blt(line2, 0, 0, line1.width, line1.height, contentSx, contentSy + (60 * 1)); this.contents.blt(line3, 0, 0, line1.width, line1.height, contentSx, contentSy + (60 * 2)); this.contents.blt(line4, 0, 0, line1.width, line1.height, contentSx, contentSy + (60 * 3)); this.contents.blt(line5, 0, 0, line1.width, line1.height, contentSx, contentSy + (60 * 4)); } createLevelBitmap(label, level) { const bitmap = this.createLineBitmap(); const lineHeight = this.lineHeight(); bitmap.textColor = '#FFFFFF'; bitmap.fontFace = $gameSystem.mainFontFace(); bitmap.outlineWidth = 1; bitmap.fontSize = 42; bitmap.drawText(`${TextResource.getText(label)}`, 744, 0, 280, lineHeight, 'left'); const braveLevel = PluginUtils.getVariables(param.braveLevel); bitmap.fontFace = 'MPLUS1Code-Regular'; bitmap.drawText(`${level}`, 1024, 0, 120, lineHeight, 'right'); return bitmap; } createGaugeBitmap(width, title, value, max, gaugeHeight, titleColor = '#FFFFFF') { const height = 58; const bitmap = new Bitmap(width, height); bitmap.fontFace = 'MPLUS1Code-Regular'; bitmap.textColor = '#FFFFFF'; bitmap.outlineWidth = 1; bitmap.fontSize = 42; const gaugeMaxWidth = width - 2; // Gauge Frame const gaugeSy = (gaugeHeight < (height - 6)) ? (height - gaugeHeight - 6) : 0; bitmap.fillRect(0, gaugeSy, width, gaugeHeight, "rgba(0, 0, 0, 0.5)"); bitmap.fillRect(1, gaugeSy + 1, gaugeMaxWidth, gaugeHeight - 2, '#202020'); // Gauge Value const percent = Number(value).clamp(0, max) / max; const gaugeWidth = gaugeMaxWidth * percent; bitmap.fillRect(1, gaugeSy + 1, gaugeWidth, gaugeHeight - 2, '#9F9F9F'); const digitWidth = this.calcDigitWidth(max); // MAX const maxSx = width - 4 - digitWidth; bitmap.drawText(max, maxSx, 6, digitWidth, 52, 'right'); // Slash const slashWidth = 64; const slashSx = maxSx - slashWidth; bitmap.drawText('/', slashSx, 6, slashWidth, 52, 'center'); // Value const valueSx = slashSx - digitWidth; bitmap.drawText(value, valueSx, 6, digitWidth, 52, 'right'); bitmap.textColor = titleColor; // Title const titleWidth = valueSx; bitmap.drawText(title, 0, 6, titleWidth, 52, 'left'); return bitmap; } calcDigitWidth(value) { const digit = String(value).length; return digit * 21; } createLineBitmap() { const width = 1144; const height = this.lineHeight(); return new Bitmap(width, height); } lineHeight() { return 60; } }; //======================================================================== // クラス定義 (Window_BadState) //======================================================================== class Window_BadStates extends Window_Selectable { constructor() { super(...arguments); } setActor(actor) { if (this._actor !== actor) { this._actor = actor; this.refresh(); } } maxCols() { return 2; } colSpacing() { return 20; } rowSpacing() { return 20; } lineHeight() { return 60 + (this.itemPadding() * 2); } maxItems() { if (!!this._actor) { return this._actor.states().length; } else { return 0; } } select(index) { super.select(index); if (this.maxItems() > 0 && !!this._helpWindow) { this.callUpdateHelp(); } } updateHelp() { super.updateHelp(); const index = this.index(); const states = this._actor.states(); const state = states[index]; if (!!state) { const baseText = state.note; // タグを除去 const regexp = /<([^<>:]+)(:?)([^>]*)>\n?/g; const text = PluginUtils.splitText(baseText.replace(regexp, ""), 21, false).join('\n'); this._helpWindow.setText(text); } } drawItemBackground() { // nothing to do } drawItem(index) { const rect = this.itemLineRect(index); const states = this._actor.states(); const state = states[index]; const iconIndex = state.iconIndex; const icon = this.createIconBitmap(iconIndex); const iconSize = 50; const iconSy = (rect.height - iconSize) / 2; this.contents.blt(icon, 0, 0, icon.width, icon.height, rect.x, rect.y + iconSy, iconSize, iconSize); this.contents.fontSize = 40; const levelWidth = 100; const levelSx = (rect.x + rect.width) - levelWidth; const level = this._actor._stateLevels[state.id]; if (!!level) { this.contents.drawText(`(${level})`, levelSx, rect.y, levelWidth, this.lineHeight(), 'right'); } const nameSx = rect.x + 60; const nameWidth = levelSx; this.contents.drawText(state.name, nameSx, rect.y, nameWidth, this.lineHeight(), 'left'); } createIconBitmap(iconIndex) { const pw = ImageManager.iconWidth; const ph = ImageManager.iconHeight; const bitmap = new Bitmap(pw, ph); if (iconIndex > 0) { const iconSet = ImageManager.loadSystem("IconSet"); const sx = (iconIndex % 16) * pw; const sy = Math.floor(iconIndex / 16) * ph; bitmap.blt(iconSet, sx, sy, pw, ph, 0, 0); } return bitmap; } }; //======================================================================== // クラス定義 (Window_CustomSkillStatus) //======================================================================== class Window_CustomSkillStatus extends Window_SkillStatus { constructor(rect) { super(...arguments); } lineHeight() { return 52; } drawActorSimpleStatus(actor, x, y) { const lineHeight = this.lineHeight(); const line1 = this.createLineBitmap(); line1.textColor = '#FFFFFF'; line1.fontFace = $gameSystem.mainFontFace(); line1.outlineWidth = 1; line1.fontSize = 42; line1.drawText(actor.name(), 0, 0, 300, lineHeight, 'left'); const hpGauge = this.createGaugeBitmap(400, TextResource.getText(MENU_TITLE_HP), actor.hp, actor.mhp, 10); line1.blt(hpGauge, 0, 0, hpGauge.width, hpGauge.height, 300, 0); const mpGauge = this.createGaugeBitmap(400, TextResource.getText(MENU_TITLE_MP), actor.mp, actor.mmp, 10); line1.blt(mpGauge, 0, 0, mpGauge.width, mpGauge.height, 720, 0); const line2 = this.createLineBitmap(); line2.textColor = '#BCBCBC'; line2.fontFace = $gameSystem.mainFontFace(); line2.outlineWidth = 1; line2.fontSize = 42; line2.drawText(actor.currentClass().name, 0, 0, 300, lineHeight, 'left'); const tpGauge = this.createGaugeBitmap(820, TextResource.getText(MENU_TITLE_TP), actor.tp, 100, 34, '#FFFFFF'); line2.blt(tpGauge, 0, 0, tpGauge.width, tpGauge.height, 300, 0); const contentSx = 76; const contentSy = 12; this.contents.blt(line1, 0, 0, line1.width, line1.height, contentSx, contentSy); this.contents.blt(line2, 0, 0, line1.width, line1.height, contentSx, contentSy + 58); } createLineBitmap() { const width = 1144; const height = this.lineHeight(); return new Bitmap(width, height); } createGaugeBitmap(width, title, value, max, gaugeHeight, titleColor = '#FFFFFF') { const height = 52; const bitmap = new Bitmap(width, height); bitmap.fontFace = 'MPLUS1Code-Regular'; bitmap.textColor = '#FFFFFF'; bitmap.outlineWidth = 1; bitmap.fontSize = 36; const gaugeMaxWidth = width - 2; // Gauge Frame const gaugeSy = (gaugeHeight < (height - 6)) ? (height - gaugeHeight - 6) : 0; bitmap.fillRect(0, gaugeSy, width, gaugeHeight, "rgba(0, 0, 0, 0.5)"); bitmap.fillRect(1, gaugeSy + 1, gaugeMaxWidth, gaugeHeight - 2, '#202020'); // Gauge Value const percent = Number(value).clamp(0, max) / max; const gaugeWidth = gaugeMaxWidth * percent; bitmap.fillRect(1, gaugeSy + 1, gaugeWidth, gaugeHeight - 2, '#9F9F9F'); const digitWidth = this.calcDigitWidth(max); // MAX const maxSx = width - 4 - digitWidth; bitmap.drawText(max, maxSx, 6, digitWidth, 52, 'right'); // Slash const slashWidth = 64; const slashSx = maxSx - slashWidth; bitmap.drawText('/', slashSx, 6, slashWidth, 52, 'center'); // Value const valueSx = slashSx - digitWidth; bitmap.drawText(value, valueSx, 6, digitWidth, 52, 'right'); bitmap.textColor = titleColor; // Title const titleWidth = valueSx; bitmap.drawText(title, 0, 6, titleWidth, 52, 'left'); return bitmap; } calcDigitWidth(value) { const digit = String(value).length; return digit * 21; } }; //======================================================================== // クラス定義 (Window_Notice) //======================================================================== class Window_Notice extends Window_Base { constructor(rect) { super(...arguments); this._label = ""; this._handlers = {}; } setText(label) { if (this._label !== label) { this._label = label; this.refresh(); } } clear() { this.setText(null); } setOkHandler(method) { this.setHandler('ok', method); } setCancelHandler(method) { this.setHandler('cancel', method); } setHandler(symbol, method) { this._handlers[symbol] = method; } isOpenAndActive() { return this.isOpen() && this.visible && this.active; } refresh() { const rect = this.baseTextRect(); this.contents.clear(); if (!!this._label && this._label !== "") { const text = TextResource.getText(this._label); this.contents.fontSize = 38; const lineHeight = 56; text.split('\n').forEach((line, index) => { this.drawText(line, rect.x, rect.y + (index * lineHeight), rect.width, 'center'); }); } } isOkTriggered() { return Input.isRepeated(InputClass.INPUT_CLASS_OK); } isCancelTriggered() { return Input.isRepeated(InputClass.INPUT_CLASS_CANCEL); } callHandler(symbol) { if (!!this._handlers[symbol]) { this._handlers[symbol](); } } processOk() { SoundManager.playOk(); this.callHandler("ok"); this.close(); } processCancel() { SoundManager.playCancel(); this.callHandler("cancel"); this.close(); } processHandling() { if (this.isOpenAndActive()) { if (!!this._handlers["ok"] && this.isOkTriggered()) { this.processOk(); } if (!!this._handlers["cancel"] && this.isCancelTriggered()) { this.processCancel(); } } } processTouch() { if (this.isOpenAndActive()) { if (TouchInput.isClicked()) { this.processOk(); } else if (TouchInput.isCancelled()) { this.processCancel(); } } } update() { this.processHandling(); this.processTouch(); super.update(); } }; //======================================================================== // クラス定義 (Scene_CustomMenu) //======================================================================== class Scene_CustomMenu extends Scene_MenuBase { constructor() { super(...arguments); this._commandWindow = null; this._actorStatesWindow = null; this._badStatesWindow = null; this._helpWindow = null; // create by base class const targetActor = $gameActors.actor(param.actor); $gameParty.setMenuActor(targetActor); } needsCancelButton() { return false; } create() { super.create(); const bitmap = new Bitmap(Graphics.width, Graphics.height); bitmap.fillAll('#000000'); this._backSprite = new Sprite(bitmap); this._backSprite.opacity = PluginUtils.percent(255, 60); this.addChild(this._backSprite); this._backSprite.hide(); ImageManager.loadPictureAsync('500System/minimap').then(minimapBitmap => { this.minimapSprite = new Sprite(minimapBitmap); this.addChild(this.minimapSprite); this.minimapSprite.hide(); const x = (Graphics.width - minimapBitmap.width) / 2; const y = (Graphics.height - minimapBitmap.height) / 2; this.minimapSprite.move(x, y); }); this.createHelpWindow(); this.createCommandWindow(); this.createActorStatesWindow(); this.createBadStatesWindow(); this.createAlbumNoticeWindow(); const actor = this.actor(); const sprite = new Sprite(ImageManager.loadSystem('im_menu/menu_effect')); sprite.zIndex = 100; sprite.visible = ((actor.tp / 100) * 100) > 75; this.addChild(sprite); } helpWindowRect() { return new Rectangle(20, 756, 570, 304); } commandWindowRect() { return new Rectangle(20, 20, 570, 726); } createCommandWindow() { const rect = this.commandWindowRect(); const commandWindow = new Window_CustomMenuCommand(rect); commandWindow.initCommandPosition(); commandWindow.setHandler('item', this.commandItem.bind(this)); commandWindow.setHandler('skill', this.commandSkill.bind(this)); commandWindow.setHandler('lewdStatus', this.commandLewdStatus.bind(this)); commandWindow.setHandler('badState', this.commandBadState.bind(this)); commandWindow.setHandler('map', this.commandMap.bind(this)); commandWindow.setHandler('options', this.commandOptions.bind(this)); commandWindow.setHandler('album', this.commandAlbum.bind(this)); commandWindow.setHandler('load', this.commandLoad.bind(this)); commandWindow.setHandler('save', this.commandSave.bind(this)); commandWindow.setHandler("cancel", this.popScene.bind(this)); commandWindow.setHelpWindow(this._helpWindow); this.addWindow(commandWindow); this._commandWindow = commandWindow; } createActorStatesWindow() { const rect = new Rectangle(600, 20, 1300, 520); const actorStatesWindow = new Window_ActorStates(rect); actorStatesWindow.setActor(this.actor()); this.addWindow(actorStatesWindow); this._actorStatesWindow = actorStatesWindow; } createBadStatesWindow() { const rect = new Rectangle(600, 550, 1300, 510); const badStatesWindow = new Window_BadStates(rect); badStatesWindow.deactivate(); badStatesWindow.setHelpWindow(this._helpWindow); badStatesWindow.setActor(this.actor()); badStatesWindow.setHandler("cancel", this.onBadStatesCancel.bind(this)); this.addWindow(badStatesWindow); this._badStatesWindow = badStatesWindow; } createAlbumNoticeWindow() { const noticeWindowRect = new Rectangle(505, 295, 910, 490); const noticeWindow = new Window_Notice(noticeWindowRect); noticeWindow.setText(NOTICE_TEXT_ALBUM); noticeWindow.setOkHandler(this.onOkAlbumNotice.bind(this)); noticeWindow.setCancelHandler(this.onCancelAlbumNotice.bind(this)); noticeWindow.close(); noticeWindow.hide(); this.addWindow(noticeWindow); this._noticeWindow = noticeWindow; } onOkAlbumNotice() { SceneManager.pop(); PluginUtils.fireCommonEvent(58); // 回想部屋に移動 } onCancelAlbumNotice() { this._noticeWindow.deactivate(); this._commandWindow.activate(); } commandItem() { SceneManager.push(Scene_Item); } commandSkill() { SceneManager.push(Scene_Skill); } commandMap() { this._backSprite.show(); this.minimapSprite.show(); } commandOptions() { SceneManager.push(Scene_Options); } commandAlbum() { this._noticeWindow.show(); this._noticeWindow.open(); this._noticeWindow.activate(); } commandLewdStatus() { SceneManager.push(SceneLewdStatus); } commandBadState() { this._badStatesWindow.activate(); this._badStatesWindow.select(0); } commandLoad() { SceneManager.push(Scene_Load); } commandSave() { SceneManager.push(Scene_Save); } onBadStatesCancel() { this._badStatesWindow.deselect(); this._commandWindow.activate(); } update() { super.update(); if (this.minimapSprite?.visible) { if (TouchInput.isCancelled() || Input.isTriggered('cancel')) { SoundManager.playCancel(); this._backSprite.hide(); this.minimapSprite.hide(); this._commandWindow.activate(); } } } }; //======================================================================== // コアスクリプト変更部 (Scene_Skill) //======================================================================== const _Scene_Skill_prototype_createStatusWindow = Scene_Skill.prototype.createStatusWindow; Scene_Skill.prototype.createStatusWindow = function() { const rect = this.statusWindowRect(); this._statusWindow = new Window_CustomSkillStatus(rect); this.addWindow(this._statusWindow); }; const _Scene_Skill_prototype_needsPageButtons = Scene_Skill.prototype.needsPageButtons; Scene_Skill.prototype.needsPageButtons = function() { return false; }; const _Scene_Skill_prototype_needsCancelButton = Scene_Skill.prototype.needsCancelButton; Scene_Skill.prototype.needsCancelButton = function() { return false; }; //======================================================================== // コアスクリプト変更部 (Scene_Map) //======================================================================== const _Scene_Map_prototype_callMenu = Scene_Map.prototype.callMenu; Scene_Map.prototype.callMenu = function() { SoundManager.playOk(); SceneManager.push(Scene_CustomMenu); $gameTemp.clearDestination(); this._mapNameWindow.hide(); this._waitCount = 2; }; //======================================================================== // コアスクリプト変更部 (Game_Interpreter) //======================================================================== const _Game_Interpreter_prototype_command351 = Game_Interpreter.prototype.command351; Game_Interpreter.prototype.command351 = function() { if (!$gameParty.inBattle()) { SceneManager.push(Scene_CustomMenu); } return true; }; })();