//==============================================================================
// Komado.js ver.1.01
//==============================================================================
/*:
* @plugindesc 子窓プラグイン
* @author 奏ねこま(おとぶきねこま)
* @url http://makonet.sakura.ne.jp/rpg_tkool
* @target MZ
*
* @param exclude plugin
* @type string[]
* @default []
* @desc 子窓で無効にするプラグイン
*
* @help
* 本プラグインの利用方法については下記マニュアルをご参照ください。
* http://makonet.sakura.ne.jp/rpg_tkool/MVMZ/Komado/document.html
*
* ------------------------------------------------------------------------------
* 本プラグインの利用はRPGツクール/RPG Makerの正規ユーザーに限られます。
* 商用、非商用、有償、無償、一般向け、成人向けを問わず利用可能です。
* ご利用の際に連絡や報告は必要ありません。また、製作者名の記載等も不要です。
* プラグインを導入した作品に同梱する形以外での再配布、転載はご遠慮ください。
* 本プラグインにより生じたいかなる問題についても一切の責任を負いかねます。
* ------------------------------------------------------------------------------
* Copylight (c) 2020 Nekoma Otobuki
* http://makonet.sakura.ne.jp/rpg_tkool/
* https://twitter.com/koma_neko
*/
(()=>{
'use strict';
if (!Utils.isNwjs()) {
return;
}
let $p = (p => ({
'exclude plugin': eval(p['exclude plugin']),
'index.html': '',
'js/main.js': '',
'resetListener': [],
'render count': 0
}))(PluginManager.parameters('Komado'));
function addResetListener(listener) {
$p['resetListener'].push(listener);
}
function callResetListener() {
let listener;
while (listener = $p['resetListener'].shift()) {
listener();
}
}
if (!opener || opener == global) { /* Main Window */
(fs => {
let html = process.mainModule.filename;
let js = html.replace(/\/index.html/, '/js/main.js');
fs.readFile(html, 'utf8', (err, data) => $p['index.html'] = data);
fs.readFile(js, 'utf8', (err, data) => $p['js/main.js'] = data);
})(require('fs'));
//==============================================================================
// DataManager
//==============================================================================
(__extractSaveContents => {
DataManager.extractSaveContents = function(contents) {
__extractSaveContents.apply(this, arguments);
$gameScreen._komados = $gameScreen._komados || [];
};
})(DataManager.extractSaveContents);
//==============================================================================
// SceneManager
//==============================================================================
(__updateScene => {
SceneManager.updateScene = function() {
__updateScene.apply(this, arguments);
if (this.isNextScene(Scene_Title) && !this._scene.isBusy() ||
this._scene instanceof Scene_Load && this.isNextScene(Scene_Map) && !this._scene.isBusy()) {
callResetListener();
}
};
})(SceneManager.updateScene);
//==============================================================================
// Game_Temp
//==============================================================================
(__initialize => {
Game_Temp.prototype.initialize = function() {
__initialize.apply(this, arguments);
this._isReadyKomado = false;
this._reservedKomadoEvent = {};
this._requestRefreshCount = 0;
};
})(Game_Temp.prototype.initialize);
//==============================================================================
// Game_System
//==============================================================================
(__initialize => {
Game_System.prototype.initialize = function() {
__initialize.apply(this, arguments);
this._komados = [];
};
})(Game_System.prototype.initialize);
Game_System.prototype.createKomado = function(mapId, x, y, width, height, options = {}) {
let komado = new Game_Komado(mapId, x, y, width, height, options);
this._komados.push(komado);
};
Game_System.prototype.updateKomado = function() {
if (!$gameTemp._isReadyKomado) {
let komados = [...this._komados].sort((a,b) => a._sortId - b._sortId);
komados.forEach(komado => komado.open());
$gameTemp._isReadyKomado = true;
}
if (this._komados.find(komado => komado.isClosed())) {
this._komados = this._komados.filter(komado => !komado.isClosed());
}
};
Game_System.prototype.callKomadoEvent = function(mapId, eventId) {
let list = $gameTemp._reservedKomadoEvent[mapId] || [];
list.push(eventId);
$gameTemp._reservedKomadoEvent[mapId] = list;
};
//==============================================================================
// Game_Screen
//==============================================================================
(__update => {
Game_Screen.prototype.update = function() {
__update.apply(this, arguments);
$gameSystem.updateKomado();
};
})(Game_Screen.prototype.update);
//==============================================================================
// Gsme_Map
//==============================================================================
(__requestRefresh => {
Game_Map.prototype.requestRefresh = function(mapId) {
__requestRefresh.apply(this, arguments);
$gameTemp._requestRefreshCount++;
};
})(Game_Map.prototype.requestRefresh);
//==============================================================================
// Game_Komado
//==============================================================================
class Game_Komado {
constructor(mapId, x, y, width, height, options = {}) {
this._mapId = mapId;
this._x = x;
this._y = y;
this._width = width;
this._height = height;
this._player = options.player || { x: 0, y: 0, transparent: false };
this._title = options.title || '';
this._alwaysOnTop = options.alwaysOnTop == null ? true : options.alwaysOnTop;
this._frame = options.frame == null ? true : options.frame;
this._show = options.show == null ? true : options.show;
this._transparent = options.transparent && !this._frame;
this._dragBox = this._frame ? null : options.dragBox;
this._minimizeBox = this._frame ? null : options.minimizeBox;
this._closeBox = this._frame ? null : options.closeBox;
this._excludePlugin = options.excludePlugin || [];
this._closed = false;
this._sortId = Date.now();
this.open();
}
open() {
let js = this.createMainJs();
let html = this.createIndexHtml(js);
let options = {
width: this._width,
height: this._height,
frame: this._frame,
transparent: this._transparent,
show: false,
resizable: false,
show_in_taskbar: false
};
nw.Window.open(html, options, win => {
(fs => {
fs.unlinkSync(html);
win.window.addEventListener('load', () => fs.unlinkSync(js));
})(require('fs'));
this.setup(win);
});
}
createMainJs() {
let file = (path => path.join(path.dirname(location.pathname), `${Date.now()}.js`))(require('path')).replace(/^[\\/]/, '');
let js = $p['js/main.js'];
let plugins = JSON.stringify($plugins.filter(plugin => ![...$p['exclude plugin'],...this._excludePlugin].includes(plugin.name)));
let dataKomado = JSON.stringify({ width: this._width, height: this._height, mapId: this._mapId, player: this._player, show: this._show, transparent: this._transparent, minimizeBox: this._minimizeBox, closeBox: this._closeBox });
let script = `\$plugins = ${plugins}; window.\$dataKomado = ${dataKomado};`;
js = js.replace(/(?=PluginManager.setup)/, script);
require('fs').writeFileSync(file, js);
return file;
}
createIndexHtml(jsFile) {
let file = (path => path.join(path.dirname(location.pathname), `${Date.now()}.html`))(require('path')).replace(/^[\\/]/, '');
let html = $p['index.html'];
let title = this._title || $dataSystem.gameTitle;
html = html.replace(/(?<=
).*(?=<\/title>)/, title)
.replace(/js\/main.js/, jsFile);
require('fs').writeFileSync(file, html);
return file;
}
setup(win) {
this.setupWindow(win);
this.setupEvent(win);
}
setupWindow(win) {
win.x = this._x - (this._frame ? 2 : 0);
win.y = this._y;
let frameWidth = win.window.outerWidth - win.window.innerWidth;
let frameHeight = win.window.outerHeight - win.window.innerHeight;
let width = this._width - (win.width - this._width) + frameWidth;
let height = this._height - (win.height - this._height) + frameHeight;
win.resizeTo(width, height);
}
setupEvent(win) {
let main = nw.Window.get();
let onfocus = () => {
if (this._alwaysOnTop) {
win.setAlwaysOnTop(true);
win.setAlwaysOnTop(false);
}
};
let onminimize = () => win.minimize();
let onmaximize = () => onfocus();
let onrestore = () => win.restore();
let onresize = () => onfocus();
let onmousedown = () => this._alwaysOnTop && win.setAlwaysOnTop(true);
let onmouseup = () => onfocus();
let onclosed = () => {
if (!this._closed) {
win.close();
}
main.removeListener('minimize', onminimize);
main.removeListener('maximize', onmaximize);
main.removeListener('resize', onresize);
main.removeListener('restore', onrestore);
main.removeListener('closed', onclosed);
removeEventListener('focus', onfocus);
removeEventListener('mousedown', onmousedown);
removeEventListener('mouseup', onmouseup);
removeEventListener('unload', onunload);
};
let onunload = () => onclosed();
let onend = () => onclosed();
win.on('loaded', () => {
let document = win.window.document;
if (!this._frame) {
if (this._dragBox) {
let div = document.createElement('div');
div.style.position = 'absolute';
div.style.left = this._dragBox.x + 'px';
div.style.top = this._dragBox.y + 'px';
div.style.width = this._dragBox.width + 'px';
div.style.height = this._dragBox.height + 'px';
div.style.zIndex = 100;
div.style['-webkit-app-region'] = 'drag';
document.body.appendChild(div);
}
if (this._minimizeBox) {
let left = this._minimizeBox.x;
let top = this._minimizeBox.y;
let right = left + this._minimizeBox.width;
let bottom = top + this._minimizeBox.height;
document.addEventListener('click', event => {
let x = event.pageX;
let y = event.pageY;
if (x >= left && y >= top && x <= right && y <= bottom) {
win.minimize();
}
});
}
if (this._closeBox) {
let left = this._closeBox.x;
let top = this._closeBox.y;
let right = left + this._closeBox.width;
let bottom = top + this._closeBox.height;
document.addEventListener('click', event => {
let x = event.pageX;
let y = event.pageY;
if (x >= left && y >= top && x <= right && y <= bottom) {
win.close();
}
});
}
}
if (this._transparent) {
document.body.style.backgroundColor = '';
}
});
win.on('focus', () => {
main.removeListener('resize', onresize);
removeEventListener('focus', onfocus);
removeEventListener('mousedown', onmousedown);
removeEventListener('mouseup', onmouseup);
main.on('resize', onresize);
addEventListener('focus', onfocus);
addEventListener('mousedown', onmousedown);
addEventListener('mouseup', onmouseup);
this._sortId = Date.now();
});
win.on('move', (x, y) => {
this._x = x + (this._frame ? 2 : 0);
this._y = y;
});
win.on('minimize', () => main.minimize());
win.on('closed', () => {
this._closed = true;
onclosed();
});
main.on('minimize', onminimize);
main.on('maximize', onmaximize);
main.on('resize', onresize);
main.on('restore', onrestore);
main.on('closed', onclosed);
addEventListener('focus', onfocus);
addEventListener('mousedown', onmousedown);
addEventListener('mouseup', onmouseup);
addEventListener('unload', onunload);
addResetListener(onend);
}
isClosed() {
return this._closed;
}
}
window.Game_Komado = Game_Komado;
} else { /* Sub Window */
if (Utils.RPGMAKER_NAME == 'MV') {
SceneManager._screenWidth = $dataKomado.width;
SceneManager._screenHeight = $dataKomado.height;
SceneManager._boxWidth = $dataKomado.width;
SceneManager._boxHeight = $dataKomado.height;
}
function isControlBox(x, y) {
if (!$dataKomado.transparent) return false;
let minimizeBox = $dataKomado.minimizeBox;
if (minimizeBox) {
let left = minimizeBox.x;
let top = minimizeBox.y;
let right = left + minimizeBox.width;
let bottom = top + minimizeBox.height;
if (x >= left && y >= top && x <= right && y <= bottom) {
return true;
}
}
let closeBox = $dataKomado.closeBox;
if (closeBox) {
let left = closeBox.x;
let top = closeBox.y;
let right = left + closeBox.width;
let bottom = top + closeBox.height;
if (x >= left && y >= top && x <= right && y <= bottom) {
return true;
}
}
return false;
}
//==============================================================================
// PIXI
//==============================================================================
(() => {
let _renderer = {};
function CanvasWebGLRenderer(target, prop) {
if (!_renderer[prop]) {
let renderer = function(options, arg2, arg3) {
if ($dataKomado.transparent) {
arg3.transparent = true;
}
target[prop].call(this, options, arg2, arg3);
};
renderer.prototype = Object.create(target[prop].prototype);
renderer.prototype.constructor = renderer;
_renderer[prop] = renderer;
}
return _renderer[prop];
}
function autoDetectRenderer(target, prop) {
if (!_renderer[prop]) {
let renderer = function(options, arg1, arg2, arg3) {
if ($dataKomado.transparent) {
arg2.transparent = true;
}
return target[prop].call(this, options, arg1, arg2, arg3);
};
_renderer[prop] = renderer;
}
return _renderer[prop];
}
function Application(target, prop) {
if (!_renderer[prop]) {
let renderer = function(options) {
if ($dataKomado.transparent) {
options.transparent = true;
}
return target[prop].call(this, options);
};
renderer.prototype = Object.create(target[prop].prototype);
renderer.prototype.constructor = renderer;
_renderer[prop] = renderer;
}
return _renderer[prop];
}
PIXI = new Proxy(PIXI, {
get: (target, prop) => {
if (Utils.RPGMAKER_NAME == 'MV') {
if (['CanvasRenderer','WebGLRenderer'].includes(prop)) {
return CanvasWebGLRenderer(target, prop);
}
if (prop == 'autoDetectRenderer') {
return autoDetectRenderer(target, prop);
}
}
if (Utils.RPGMAKER_NAME == 'MZ') {
if (prop == 'Application') {
return Application(target, prop);
}
}
return target[prop];
}
});
})();
//==============================================================================
// Graphics
//==============================================================================
Graphics._defaultStretchMode = function() {
return false;
};
Graphics._switchStretchMode = function() {
};
Graphics._switchFullScreen = function() {
};
if (Utils.RPGMAKER_NAME == 'MZ') {
Graphics._createErrorPrinter = function() {
this._errorPrinter = document.createElement("div");
this._errorPrinter.id = "errorPrinter";
this._errorPrinter.innerHTML = this._makeErrorHtml();
this._updateErrorPrinter();
document.body.appendChild(this._errorPrinter);
};
Graphics._updateErrorPrinter = function() {
const width = this._width * this._realScale;
const height = Math.min(this._height, 100) * this._realScale;
this._errorPrinter.style.width = width + "px";
this._errorPrinter.style.height = height + "px";
};
}
//==============================================================================
// TouchInput
//==============================================================================
(___onMouseDown => {
TouchInput._onMouseDown = function(event) {
if (isControlBox(event.pageX, event.pageY)) return;
___onMouseDown.apply(this, arguments);
};
})(TouchInput._onMouseDown);
(___onWheel => {
TouchInput._onWheel = function(event) {
if (isControlBox(event.pageX, event.pageY)) {
event.preventDefault();
return;
}
___onWheel.apply(this, arguments);
};
})(TouchInput._onWheel);
(___onTouchStart => {
TouchInput._onTouchStart = function(event) {
if (isControlBox(event.pageX, event.pageY)) {
event.preventDefault();
return;
}
___onTouchStart.apply(this, arguments);
};
})(TouchInput._onTouchStart);
//==============================================================================
// DataManager
//==============================================================================
(__isSkill => {
DataManager.isSkill = function(item) {
return __isSkill.apply(this, arguments) || (item && opener.$dataSkills.contains(item));
};
})(DataManager.isSkill);
(__isItem => {
DataManager.isItem = function(item) {
return __isItem.apply(this, arguments) || (item && opener.$dataItems.contains(item));
};
})(DataManager.isItem);
(__isWeapon => {
DataManager.isWeapon = function(item) {
return __isWeapon.apply(this, arguments) || (item && opener.$dataWeapons.contains(item));
};
})(DataManager.isWeapon);
(__isArmor => {
DataManager.isArmor = function(item) {
return __isArmor.apply(this, arguments) || (item && opener.$dataArmors.contains(item));
};
})(DataManager.isArmor);
(__makeSaveContents => {
DataManager.makeSaveContents = function() {
let contents = __makeSaveContents.apply(this, arguments);
contents.actors = opener.$gameActors;
return contents;
};
})(DataManager.makeSaveContents);
(__extractSaveContents => {
DataManager.extractSaveContents = function(contents) {
__extractSaveContents.apply(this, arguments);
$gameVariables = opener.$gameVariables;
$gameSwitches = opener.$gameSwitches;
$gameSelfSwitches = opener.$gameSelfSwitches;
$gameActors._data = [];
};
})(DataManager.extractSaveContents);
//==============================================================================
// SceneManager
//==============================================================================
(__isGameActive => {
SceneManager.isGameActive = function() {
__isGameActive.apply(this, arguments);
return true;
};
})(SceneManager.isGameActive);
(__update => {
SceneManager.update = function() {
if (this._scene instanceof Scene_Map) {
if ($p['render count'] == 1) {
if ($dataKomado.show) {
nw.Window.get().show();
}
}
if ($p['render count'] < 2) {
if (Utils.RPGMAKER_NAME == 'MV' && this.isCurrentSceneStarted() && Graphics._rendered ||
Utils.RPGMAKER_NAME == 'MZ' && this._scene.isStarted()) {
$p['render count']++;
}
}
}
__update.apply(this, arguments);
};
})(SceneManager.update);
(__onKeyDown => {
SceneManager.onKeyDown = function(event) {
if (![116,119].includes(event.keyCode) || event.ctrlKey || event.altKey) {
__onKeyDown.apply(this, arguments);
}
};
})(SceneManager.onKeyDown);
//==============================================================================
// Scene_Boot
//==============================================================================
Scene_Boot.prototype.start = function() {
$dataSystem.startMapId = $dataKomado.mapId;
$dataSystem.startX = $dataKomado.player.x || 0;
$dataSystem.startY = $dataKomado.player.y || 0;
$dataSystem.optTransparent = !!$dataKomado.player.transparent;
Scene_Base.prototype.start.call(this);
SoundManager.preloadImportantSounds();
this.checkPlayerLocation();
DataManager.setupNewGame();
$gameVariables = opener.$gameVariables;
$gameSwitches = opener.$gameSwitches;
$gameSelfSwitches = opener.$gameSelfSwitches;
$gamePlayer._fadeType = 2;
SceneManager.goto(Scene_Map);
if (Utils.RPGMAKER_NAME == 'MZ') {
$dataSystem.advanced.screenWidth = $dataKomado.width;
$dataSystem.advanced.screenHeight = $dataKomado.height;
$dataSystem.advanced.uiAreaWidth = $dataKomado.width;
$dataSystem.advanced.uiAreaHeight = $dataKomado.height;
this.resizeScreen();
}
};
//==============================================================================
// Spriteset_Base
//==============================================================================
(__createBaseSprite => {
Spriteset_Base.prototype.createBaseSprite = function() {
__createBaseSprite.apply(this, arguments);
if ($dataKomado.transparent) {
this._blackScreen.opacity = 0;
}
};
})(Spriteset_Base.prototype.createBaseSprite);
//==============================================================================
// Game_Temp
//==============================================================================
(__initialize => {
Game_Temp.prototype.initialize = function() {
__initialize.apply(this, arguments);
this._requestRefreshCount = 0;
};
})(Game_Temp.prototype.initialize);
//==============================================================================
// Game_Actors
//==============================================================================
(__actor => {
Game_Actors.prototype.actor = function(actorId) {
let isNew = !this._data[actorId];
let actor = __actor.apply(this, arguments);
if (actor && isNew) {
this._data[actorId] = new Proxy(actor, {
get: (target, prop) => {
if (typeof target[prop] != 'function') {
return opener.$gameActors.actor(target._actorId)[prop];
}
return target[prop];
},
set: (target, prop, value) => {
if (typeof value != 'function') {
opener.$gameActors.actor(target._actorId)[prop] = value;
} else {
target[prop] = value;;
}
}
});
}
return actor;
};
})(Game_Actors.prototype.actor);
//==============================================================================
// Game_Map
//==============================================================================
(__update => {
Game_Map.prototype.update = function(sceneActive) {
let list = opener.$gameTemp._reservedKomadoEvent[this._mapId];
if (list) {
delete opener.$gameTemp._reservedKomadoEvent[this._mapId];
list.forEach(eventId => {
let event;
if (typeof eventId == 'number') {
event = this.event(eventId);
} else {
event = this.events().filter(event => {
return (event.event().meta['komadoevent'] ||
event.event().meta['KomadoEvent']) == eventId;
})[0];
}
if (event) {
event.start();
}
});
}
if ($gameTemp._requestRefreshCount != opener.$gameTemp._requestRefreshCount) {
$gameTemp._requestRefreshCount = opener.$gameTemp._requestRefreshCount;
this._needsRefresh = true;
}
__update.apply(this, arguments);
};
})(Game_Map.prototype.update);
}
})();