//============================================================================= // RPG Maker MZ - RegionSetting // // Copyright 2024 Panzer-IV. 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 四号戦車 * @base PluginCommonBase * @base DebugSwitch * @base TextResource * @base PluginUtils * @orderAfter PluginCommonBase * @orderAfter DebugSwitch * @orderAfter TextResource * @orderAfter PluginUtils * * @param regions * @text リージョン設定 * @desc リージョンと効果の指定です。 * @type struct[] * @default [] * * @param passageSetting * @text 通行不可デフォルト設定 * @desc 通行不可リージョンが設定されていない * タイルの通行設定 * @type select * @default default_passage * @option ツクールの設定に従う * @value default_passage * @option 全て通行可 * @value all_passible * @option 全て通行不可 * @value all_not_passible * * * @help RegionSetting.js * * Version: 0.0.3 * * マップリージョンに特殊処理を持たせる設定プラグイン * */ /*~struct~RegionSetting: * * @param name * @text 設定名 * @desc 設定用の名前です。 * 入力時識別用にお使い下さい。 * @type string * @default * * @param region * @text リージョン番号 * @desc 指定リージョンの番号です。 * @type number * @min 0 * @default 0 * * @param effect * @text 効果 * @desc 指定リージョンに付与する効果を指定します。 * @type select * @default none * @option なし * @value none * @option 通行不可 * @value blockPassible * @option 左方向だけ移動不可 * @value onlyLeftBlock * @option 上方向だけ移動不可 * @value onlyUpBlock * @option 右方向だけ移動不可 * @value onlyRightBlock * @option 下方向だけ移動不可 * @value onlyDownBlock * @option 上下のみ移動可能 * @value onlyVirtical * @option 左右のみ移動可能 * @value onlyHorizontal * @option 左と上だけ移動不可 * @value onlyUpLeftBlock * @option 上と右だけ移動不可 * @value onlyUpRightBlock * @option 右と下だけ移動不可 * @value onlyDownRightBlock * @option 下と左だけ移動不可 * @value onlyDownLeftBlock * @option 強制通行 * @value forcePassible * @option 通行不可(キャラクターの描画をマップより上に) * @value blockPassibleWithOverlayTile * @option 強制的にマップより優先表示(☆無視) * @value overlayTile * * @param maskOnFarPlayer * @text 近づくと消える壁設定 * @text ONにすると「近づくと消える壁」に出来ます。 * @type boolean * @default false * */ (() => { "use strict"; //======================================================================== // プラグイン定義 //======================================================================== const pluginName = "RegionSetting"; const script = document.currentScript; const param = PluginUtils.reparseParameter(script); //======================================================================== // 定数定義 //======================================================================== const DIRECTION_UP = 8; const DIRECTION_LEFT = 4; const DIRECTION_RIGHT = 6; const DIRECTION_DOWN = 2; const checkDirection = (direction, ...blockdirections) => { return !blockdirections.some(dir => dir === direction); }; //======================================================================== // クラス定義 (Sprite_MapMask) //======================================================================== class Sprite_MapMask extends Sprite { constructor(mask) { super(new Bitmap($gameMap.tileWidth(), $gameMap.tileHeight())); this._mapMask = mask; this.bitmap.fillAll('#000000'); } get group() { return this._mapMask?.group; } set maskVisible(value) { if (!!this._mapMask) { this._mapMask.visible = value; } } update() { super.update(); this.updatePosition(); this.updateOpacity(); } updatePosition() { if (!!this._mapMask) { this.x = this._mapMask.screenX(); this.y = this._mapMask.screenY(); this.z = 6; } } isNearThePlayer() { if (!!this._mapMask) { return this._mapMask.isNearThePlayer(); } return false; } updateOpacity() { if (!!this._mapMask) { if (this._mapMask.isVisible()) { if (this.opacity < 255) { this.opacity += 10; if (this.opacity >= 255) { this.opacity = 255; } } } else { if (this.opacity > 0) { this.opacity -= 10; if (this.opacity < 0) { this.opacity = 0; } } } } } }; //======================================================================== // クラス定義 (Game_MapMask) //======================================================================== class Game_MapMask { constructor(mask) { this._realX = mask.x; this._realY = mask.y; this._effect = mask.effect; this._group = mask.group; this._visible = true; } get x() { return this._realX; } get y() { return this._realY; } get group() { return this._group; } set visible(value) { this._visible = value; } screenX() { const tw = $gameMap.tileWidth(); const scrolledX = $gameMap.adjustX(this._realX); return Math.floor(scrolledX * tw); } screenY() { const th = $gameMap.tileHeight(); const scrolledY = $gameMap.adjustY(this._realY); return Math.floor(scrolledY * th); } isNearThePlayer() { const sx = Math.abs($gameMap.deltaX(this._realX, $gamePlayer.x)); const sy = Math.abs($gameMap.deltaY(this._realY, $gamePlayer.y)); return sx + sy < 5; } show() { this._visible = true; } hide() { this._visible = false; } isVisible() { return this._visible; } } //======================================================================== // コアスクリプト変更部 (Game_Map) //======================================================================== const _Game_Map_prototype_setup = Game_Map.prototype.setup; Game_Map.prototype.setup = function(mapId) { _Game_Map_prototype_setup.apply(this, arguments); const width = $dataMap.width; const height = $dataMap.height; const masks = []; for (let y = 1; y <= height; y++) { for (let x = 1; x <= width; x++) { const regionId = this.regionId(x, y); const setting = param.regions.find(region => { return region.region === regionId && region.maskOnFarPlayer; }); if (!!setting) { masks.push({ x: x, y: y, effect: setting.effect, regionId, group: regionId, visible: true, }); } } } this._maskGroups = masks.map(mask => { return mask.group; }).filter((group, index, self) => { return self.indexOf(group) === index; }); this._mapMasks = masks; }; Game_Map.prototype.mapMasks = function() { return this._mapMasks; }; Game_Map.prototype.mapMaskGroups = function() { return this._maskGroups; }; //======================================================================== // コアスクリプト変更部 (Spriteset_Map) //======================================================================== const _Spriteset_Map_prototype_createCharacters = Spriteset_Map.prototype.createCharacters; Spriteset_Map.prototype.createCharacters = function() { _Spriteset_Map_prototype_createCharacters.apply(this, arguments); this._mapMaskSprites = []; for (const mask of $gameMap.mapMasks()) { this._mapMaskSprites.push(new Sprite_MapMask(new Game_MapMask(mask))); } this._mapMaskSprites.forEach(sprite => { this._tilemap.addChild(sprite); }); }; const _Spriteset_Map_prototype_update = Spriteset_Map.prototype.update; Spriteset_Map.prototype.update = function() { if (!!this._mapMaskSprites) { const maskGroups = $gameMap.mapMaskGroups(); maskGroups.forEach(group => { const groups = this._mapMaskSprites.filter(maskSprite => { return maskSprite.group === group; }); const visible = groups.every(maskSprite => { return !maskSprite.isNearThePlayer(); }) groups.forEach(maskSprite => { maskSprite.maskVisible = visible; }); }); } _Spriteset_Map_prototype_update.apply(this, arguments); }; //======================================================================== // コアスクリプト変更部 (Game_Map) //======================================================================== const _Game_Map_prototype_isPassable = Game_Map.prototype.isPassable; Game_Map.prototype.isPassable = function(x, y, d) { const regionId = this.regionId(x, y); const setting = param.regions.find(region => { return region.region === regionId; }); const passageSeeting = param.passageSetting; const defaultPassible = () => { switch (passageSeeting) { case 'all_passible': return true; case 'all_not_passible': return false; case 'default_passage': default: return _Game_Map_prototype_isPassable.apply(this, arguments); } // switch }; if (!!setting) { switch (setting.effect) { case 'blockPassible': case 'blockPassibleWithOverlayTile': return false; case 'forcePassible': return true; case 'onlyLeftBlock': return checkDirection(d, DIRECTION_LEFT); case 'onlyUpBlock': return checkDirection(d, DIRECTION_UP); case 'onlyRightBlock': return checkDirection(d, DIRECTION_RIGHT); case 'onlyDownBlock': return checkDirection(d, DIRECTION_DOWN); case 'onlyVirtical': return checkDirection(d, DIRECTION_LEFT, DIRECTION_RIGHT); case 'onlyHorizontal': return checkDirection(d, DIRECTION_UP, DIRECTION_DOWN); case 'onlyUpLeftBlock': return checkDirection(d, DIRECTION_UP, DIRECTION_LEFT); case 'onlyUpRightBlock': return checkDirection(d, DIRECTION_UP, DIRECTION_RIGHT); case 'onlyDownRightBlock': return checkDirection(d, DIRECTION_DOWN, DIRECTION_RIGHT); case 'onlyDownLeftBlock': return checkDirection(d, DIRECTION_DOWN, DIRECTION_LEFT); default: return defaultPassible(); } // switch } else { return defaultPassible(); } }; Game_Map.prototype.isOverlayTile = function(x, y) { const regionId = this.regionId(x, y); const setting = param.regions.find(region => { return region.region === regionId; }); return !!setting && [ 'blockPassibleWithOverlayTile', 'overlayTile', ].some(effect => setting.effect === effect); }; Game_Map.prototype.isBlockPassible = function(x, y) { const regionId = this.regionId(x, y); const setting = param.regions.find(region => { return region.region === regionId; }); return !!setting && setting.effect === 'blockPassible'; }; //======================================================================== // コアスクリプト変更部 (Game_Event) //======================================================================== const _Game_Event_start = Game_Event.prototype.start; Game_Event.prototype.start = function() { if (this.isTriggerIn([0, 1])) { // プレイヤーが侵入できない箇所にいるイベントはインタラクトもさせない const x = $gamePlayer.x; const y = $gamePlayer.y; const d = $gamePlayer.direction(); if (!$gameMap.isPassable(x, y, d)) { return; } } else if (this.isTriggerIn([2])) { // イベント側からプレイヤーのいる箇所に侵入不可ならインタラクトさせない const x = $gamePlayer.x; const y = $gamePlayer.y; const d = this.reverseDir(this.direction()); if (!$gameMap.isPassable(x, y, d)) { return; } } _Game_Event_start.apply(this, arguments); }; //======================================================================== // コアスクリプト変更部 (Game_Event) //======================================================================== const _Game_CharacterBase_screenZ = Game_CharacterBase.prototype.screenZ; Game_CharacterBase.prototype.screenZ = function() { const z = _Game_CharacterBase_screenZ.apply(this, arguments); if ($gameMap.isOverlayTile(this.x, this.y)) { return z + 3; } if ($gameMap.isBlockPassible(this.x, this.y - 1)) { return z + 3; } return z; }; //======================================================================== // プラグインコマンド //======================================================================== })();